Attempting Text Input
This commit is contained in:
BIN
content/FreeSans.ttf
Normal file
BIN
content/FreeSans.ttf
Normal file
Binary file not shown.
@@ -5,17 +5,13 @@
|
||||
|
||||
#include <J3ML/LinearAlgebra.h>
|
||||
#include <J3ML/LinearAlgebra/Vector2.h>
|
||||
#include "J3ML/LinearAlgebra/Vector3.h"
|
||||
#include <J3ML/LinearAlgebra/Vector3.h>
|
||||
|
||||
// OpenGL Wrapper for rendering 2D graphics primitives in both a 2D and 3D context
|
||||
namespace JGL {
|
||||
|
||||
// All functions accept coordinates in pixel-screen space [0, 600]
|
||||
// and are internally transformed to OpenGL clip space [-1, +1]
|
||||
using namespace LinearAlgebra;
|
||||
|
||||
|
||||
|
||||
struct RGBTuple {
|
||||
int r; int g; int b;
|
||||
};
|
||||
@@ -214,7 +210,12 @@ namespace JGL {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
using J3ML::LinearAlgebra::Vector2;
|
||||
using J3ML::LinearAlgebra::Vector3;
|
||||
using J3ML::LinearAlgebra::Matrix3x3;
|
||||
using J3ML::LinearAlgebra::Matrix4x4;
|
||||
using J3ML::LinearAlgebra::AxisAngle;
|
||||
using J3ML::LinearAlgebra::Quaternion;
|
||||
|
||||
struct HSV {
|
||||
float hue;
|
||||
|
295
main.cpp
295
main.cpp
@@ -1,26 +1,163 @@
|
||||
#include <GL/glut.h>
|
||||
#include "JGL/JGL.h"
|
||||
//#include <GL/glew.h>
|
||||
#include <glad/glad.h>
|
||||
#include <JGL/JGL.h>
|
||||
#include <rewindow/types/window.h>
|
||||
#include <freetype2/ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include <iostream>
|
||||
#include <LearnOpenGL/Shader.h>
|
||||
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
void initGL()
|
||||
struct Character
|
||||
{
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
glOrtho(-100.f, 100.f, -100.f, 100.f, -100.f, 100.f);
|
||||
}
|
||||
unsigned int TextureID; // ID handle of the glyph texture
|
||||
Vector2 Size; // Size of glyph
|
||||
Vector2 Bearing; // Offset from baseline to left/top of glyph
|
||||
unsigned int Advance; // Offset to advance to next glyph
|
||||
};
|
||||
|
||||
std::map<char, Character> Characters;
|
||||
unsigned int VAO, VBO;
|
||||
const std::string vertexShader = "#version 330 core\n"
|
||||
"layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>\n"
|
||||
"out vec2 TexCoords;\n"
|
||||
"\n"
|
||||
"uniform mat4 projection;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);\n"
|
||||
" TexCoords = vertex.zw;\n"
|
||||
"} ";
|
||||
const std::string fragmentShader = "#version 330 core\n"
|
||||
"layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>\n"
|
||||
"out vec2 TexCoords;\n"
|
||||
"\n"
|
||||
"uniform mat4 projection;\n"
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);\n"
|
||||
" TexCoords = vertex.zw;\n"
|
||||
"} ";
|
||||
|
||||
using J3ML::LinearAlgebra::Matrix4x4;
|
||||
|
||||
|
||||
void display() {
|
||||
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer
|
||||
glMatrixMode(GL_MODELVIEW); // To operate on the Model-View matrix
|
||||
glLoadIdentity(); // Reset the model-view matrix.
|
||||
|
||||
|
||||
// Define shapes enclosed within a pair of glBegin and glEnd
|
||||
class JGLDemoWindow : public ReWindow::RWindow
|
||||
{
|
||||
public:
|
||||
LearnOpenGL::Shader shader;
|
||||
JGLDemoWindow() : ReWindow::RWindow()
|
||||
{
|
||||
|
||||
glBegin(GL_QUADS); // Each set of 4 vertices form a quad
|
||||
}
|
||||
|
||||
void initGL()
|
||||
{
|
||||
gladLoadGL();
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
shader = LearnOpenGL::Shader(vertexShader, fragmentShader);
|
||||
Matrix4x4 projection = Matrix4x4::D3DOrthoProjLH(0.0f, 1.0f, 1280, 720);
|
||||
shader.use();
|
||||
glUniformMatrix4fv(glGetUniformLocation(shader.ID, "projection"), 1, GL_FALSE, projection.ptr());
|
||||
//initGL(); // Our own OpenGL initialization
|
||||
|
||||
FT_Library ft;
|
||||
|
||||
if (FT_Init_FreeType(&ft))
|
||||
{
|
||||
std::cout << "Error::FREETYPE: " << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
FT_Face face;
|
||||
if (FT_New_Face(ft, "content/FreeSans.ttf", 0, &face))
|
||||
{
|
||||
std::cout << "Error::FREETYPE: Failed to load font!" << std::endl;
|
||||
}
|
||||
|
||||
FT_Set_Pixel_Sizes(face, 0, 48);
|
||||
|
||||
if (FT_Load_Char(face, 'X', FT_LOAD_RENDER))
|
||||
{
|
||||
std::cout << "Error::FREETYPE: Failed to load Glyph" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // disable byte-alignment restriction
|
||||
|
||||
for (unsigned char c = 0; c < 128; c++)
|
||||
{
|
||||
// load character glyph
|
||||
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
|
||||
{
|
||||
std::cout << "ERROR::FREETYPE: Failed to load Glyph!" << std::endl;
|
||||
continue;
|
||||
}
|
||||
// Generate Texture
|
||||
unsigned int texture;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RED,
|
||||
face->glyph->bitmap.width,
|
||||
face->glyph->bitmap.rows,
|
||||
0,
|
||||
GL_RED,
|
||||
GL_UNSIGNED_BYTE,
|
||||
face->glyph->bitmap.buffer
|
||||
);
|
||||
// set textured options
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// now store character for later use
|
||||
Character character = {
|
||||
texture,
|
||||
{(float)face->glyph->bitmap.width, (float)face->glyph->bitmap.rows},
|
||||
{(float)face->glyph->bitmap_left, (float)face->glyph->bitmap_top},
|
||||
(unsigned int)face->glyph->advance.x
|
||||
};
|
||||
Characters.insert(std::pair<char, Character>(c, character));
|
||||
}
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
FT_Done_Face(face);
|
||||
FT_Done_FreeType(ft);
|
||||
|
||||
// configure VAO/VBO for texture quads
|
||||
|
||||
|
||||
glGenBuffers(6*4, &VAO);
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(float)* 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
|
||||
}
|
||||
|
||||
|
||||
void display() {
|
||||
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer
|
||||
glMatrixMode(GL_MODELVIEW); // To operate on the Model-View matrix
|
||||
glLoadIdentity(); // Reset the model-view matrix.
|
||||
|
||||
// Define shapes enclosed within a pair of glBegin and glEnd
|
||||
glBegin(GL_QUADS); // Each set of 4 vertices form a quad
|
||||
glColor3f(1.f, 0.f, 0.f);
|
||||
glVertex2f(-0.8f, 0.1f);
|
||||
glVertex2f(-0.2f, 0.1f);
|
||||
@@ -41,11 +178,10 @@ void display() {
|
||||
glVertex2f(-0.5f, -0.3f);
|
||||
glColor3f(1.f, 1.f, 1.f); // White
|
||||
glVertex2f(-0.9f, -0.3f);
|
||||
glEnd();
|
||||
glEnd();
|
||||
|
||||
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
glBegin(GL_TRIANGLES);
|
||||
glColor3f(0.0f, 0.0f, 1.f); // Blue
|
||||
glVertex2f(0.1f, -0.6f);
|
||||
glVertex2f(0.7f, -0.6f);
|
||||
@@ -57,9 +193,9 @@ void display() {
|
||||
glVertex2f(0.9f, -0.4f);
|
||||
glColor3f(0.f, 0.f, 1.f); // Blue
|
||||
glVertex2f(0.6f, -0.9f);
|
||||
glEnd();
|
||||
glEnd();
|
||||
|
||||
glBegin(GL_POLYGON); // These verts form a closed polygon
|
||||
glBegin(GL_POLYGON); // These verts form a closed polygon
|
||||
glColor3f(1.f, 1.f, 0.f); // Yellow
|
||||
glVertex2f(0.4f, 0.2f);
|
||||
glVertex2f(0.6f, 0.2f);
|
||||
@@ -67,76 +203,85 @@ void display() {
|
||||
glVertex2f(0.6f, 0.6f);
|
||||
glVertex2f(0.4f, 0.6f);
|
||||
glVertex2f(0.3f, 0.4f);
|
||||
glEnd();
|
||||
glEnd();
|
||||
|
||||
JGL::J2D::FillRect2D(JGL::Colors::White, {0, 0}, {128, 128});
|
||||
JGL::J2D::OutlineRect2D(JGL::Colors::Red, {0, 0}, {128, 128}, 4);
|
||||
JGL::J2D::DrawPixel2D(JGL::Colors::Green, {0, 0});
|
||||
JGL::J2D::FillRect2D(JGL::Colors::White, {0, 0}, {128, 128});
|
||||
JGL::J2D::OutlineRect2D(JGL::Colors::Red, {0, 0}, {128, 128}, 4);
|
||||
JGL::J2D::DrawPixel2D(JGL::Colors::Green, {0, 0});
|
||||
JGL::J2D::FillCircle2D(JGL::Colors::Purples::DarkViolet, {0, 0}, 0.75f, 64);
|
||||
|
||||
JGL::J2D::FillCircle2D(JGL::Colors::Purples::DarkViolet, {0, 0}, 0.75f, 64);
|
||||
RenderText("WHATS BOPPIN", 25.f, 25.f, 1.f, JGL::Colors::White);
|
||||
|
||||
|
||||
|
||||
glFlush(); // Render now
|
||||
}
|
||||
|
||||
int windowWidth = 640; // Windowed mode's width
|
||||
int windowHeight = 480; // Windowed mode's height
|
||||
int windowPosX = 50; // Windowed mode's top-left corner x
|
||||
int windowPosY = 50; // Windowed mode's top-left corner y
|
||||
bool fullscreenMode = true;
|
||||
|
||||
void specialKeys(int key, int x, int y) {
|
||||
switch(key) {
|
||||
case GLUT_KEY_F1:
|
||||
fullscreenMode = !fullscreenMode;
|
||||
if (fullscreenMode) {
|
||||
windowPosX = glutGet(GLUT_WINDOW_X);
|
||||
windowPosY = glutGet(GLUT_WINDOW_Y);
|
||||
windowWidth = glutGet(GLUT_WINDOW_WIDTH);
|
||||
windowHeight = glutGet(GLUT_WINDOW_HEIGHT);
|
||||
|
||||
glutFullScreen();
|
||||
} else {
|
||||
glutReshapeWindow(windowWidth, windowHeight);
|
||||
glutPositionWindow(windowPosX, windowPosY);
|
||||
}
|
||||
break;
|
||||
glFlush(); // Render now
|
||||
}
|
||||
}
|
||||
|
||||
// Handler for window re-size event. Called back when the window first appears
|
||||
// and whenever the window is re-sized with its new width and height
|
||||
void reshape(GLsizei width, GLsizei height) {
|
||||
if (height == 0) height = 1;
|
||||
GLfloat aspect = (GLfloat) width / (GLfloat) height;
|
||||
void RenderText(std::string text, float x, float y, float scale, JGL::Color3 color)
|
||||
{
|
||||
// TODO: implement shader.pushColor();
|
||||
shader.use();
|
||||
glUniform3f(glGetUniformLocation(shader.ID, "textColor"), color.r, color.g, color.b);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindBuffer(GL_VERTEX_ARRAY, VAO);
|
||||
|
||||
// Set the viewport to cover the new window
|
||||
glViewport(0, 0, width, height);
|
||||
// iterate through all characters
|
||||
std::string::const_iterator c;
|
||||
for (c = text.begin(); c != text.end(); c++)
|
||||
{
|
||||
Character ch = Characters[*c];
|
||||
float xpos = x + ch.Bearing.x * scale;
|
||||
float ypos = y - (ch.Size.y - ch.Bearing.y) * scale;
|
||||
|
||||
// Set the aspect ratio of the clipping area to match the viewport
|
||||
glMatrixMode(GL_PROJECTION); // Operate on the Projection Matrix;
|
||||
glLoadIdentity(); // Reset the projection matrix
|
||||
if (width >= height) {
|
||||
// Aspect >= 1, set the height from -1 to 1
|
||||
gluOrtho2D(-1.0 * aspect, 1.0 * aspect, -1.0, 1.0);
|
||||
} else {
|
||||
// Aspect < 1, set the width from -1 to 1, with larger height
|
||||
gluOrtho2D(-1.0, 1.0, -1.0 / aspect, 1.0 / aspect);
|
||||
float w = ch.Size.x * scale;
|
||||
float h = ch.Size.y * scale;
|
||||
|
||||
float vertices[6][4] = {
|
||||
{ xpos, ypos + h, 0.0f, 0.0f },
|
||||
{ xpos, ypos, 0.0f, 1.0f },
|
||||
{ xpos + w, ypos, 1.0f, 1.0f },
|
||||
|
||||
{ xpos, ypos + h, 0.0f, 0.0f },
|
||||
{ xpos + w, ypos, 1.0f, 1.0f },
|
||||
{ xpos + w, ypos + h, 1.0f, 0.0f }
|
||||
};
|
||||
// render glyph texture over quad
|
||||
glBindTexture(GL_TEXTURE_2D, ch.TextureID);
|
||||
// update contents of VBO memory
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // be sure to use glBufferSubData and not glBufferData
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
// render quad
|
||||
glDrawArrays(GL_TRIANGLES, 0, 6);
|
||||
// now advance cursors for next glyph (note that advance is number of 1/64 pixels)
|
||||
x += (ch.Advance >> 6) * scale;
|
||||
}
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void OnRefresh(float elapsed) override
|
||||
{
|
||||
display();
|
||||
this->glSwapBuffers();
|
||||
}
|
||||
void OnResize()
|
||||
{
|
||||
//reshape();
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
glutInit(&argc, argv); // Initialize GLUT
|
||||
glutCreateWindow("Vertex, Primitive, & Color"); // Create window with given title
|
||||
glutInitWindowSize(320, 320); // Set the window's initial width & height - non-square
|
||||
glutInitWindowPosition(50, 50); // Position the window's initial top-left corner
|
||||
glutDisplayFunc(display); // Register callback handler for window re-paint event
|
||||
glutReshapeFunc(reshape); // Register callback handler for window re-size event
|
||||
glutSpecialFunc(specialKeys); // Register callback handler for special-key event
|
||||
initGL(); // Our own OpenGL initialization
|
||||
glutMainLoop();
|
||||
JGLDemoWindow* window = new JGLDemoWindow();
|
||||
|
||||
window->init(RenderingAPI::OPENGL, "Window", 800, 600, false);
|
||||
window->initGL();
|
||||
window->setResizable(true);
|
||||
while (window->isAlive())
|
||||
{
|
||||
window->pollEvents();
|
||||
window->refresh();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user