Partial Implement RenderText

This commit is contained in:
2024-02-16 13:11:18 -05:00
parent d0eb1f34ef
commit 9406a9d429
4 changed files with 111 additions and 201 deletions

View File

@@ -58,6 +58,6 @@ include_directories(${J3ML_SOURCE_DIR}/include)
include_directories(${ReWindow_SOURCE_DIR}/include)
include_directories(${glad_SOURCE_DIR}/include)
target_link_libraries(JGL_Demo PRIVATE ${FREETYPE_LIBRARIES})
target_include_directories(JGL_Demo PRIVATE ${FREETYPE_INCLUDE_DIRS})
target_link_libraries(JGL PRIVATE ${FREETYPE_LIBRARIES})
target_include_directories(JGL PRIVATE ${FREETYPE_INCLUDE_DIRS})
target_link_libraries(JGL_Demo PUBLIC JGL ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} J3ML ReWindowLibrary GLEW glad)

View File

@@ -6,6 +6,8 @@
#include <J3ML/LinearAlgebra.h>
#include <J3ML/LinearAlgebra/Vector2.h>
#include <J3ML/LinearAlgebra/Vector3.h>
#include <string>
#include <iostream>
// OpenGL Wrapper for rendering 2D graphics primitives in both a 2D and 3D context
namespace JGL {
@@ -243,6 +245,13 @@ namespace JGL {
// TODO: Implement (CORRECT!!!) matrix transformation
}
bool InitTextEngine();
// TODO: implement correct coloring
void RenderText(std::string text, float x, float y, float scale);
namespace J2D {
void DrawPixel2D(const Color3& color, const Vector2 &coordinates);
void DrawPixel2D(const Color3& color, float x, float y);

215
main.cpp
View File

@@ -2,8 +2,6 @@
#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>
@@ -21,7 +19,7 @@ struct Character
};
std::map<char, Character> Characters;
unsigned int VAO, VBO;
GLuint VAO, VBO;
const std::string vertexShader = "attribute vec4 coord;\n"
"varying vec2 texpos;\n"
"\n"
@@ -40,10 +38,6 @@ const std::string fragmentShader = "varying vec2 texpos;\n"
using J3ML::LinearAlgebra::Matrix4x4;
GLuint program;
GLint attribute_coord;
GLint uniform_tex;
GLint uniform_color;
struct point {
@@ -57,8 +51,7 @@ class JGLDemoWindow : public ReWindow::RWindow
{
public:
LearnOpenGL::Shader shader;
FT_Face face;
FT_Library ft;
JGLDemoWindow() : ReWindow::RWindow()
{
@@ -67,203 +60,27 @@ public:
void initGL()
{
gladLoadGL();
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 1024, 768, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
if (FT_Init_FreeType(&ft))
{
std::cout << "Error::FREETYPE: " << std::endl;
return;
}
if (FT_New_Face(ft, "content/FreeSans.ttf", 0, &face))
{
std::cout << "Error::FREETYPE: Failed to load font!" << std::endl;
return;
}
shader = LearnOpenGL::Shader(vertexShader, fragmentShader);
Matrix4x4 projection = Matrix4x4::OpenGLOrthoProjRH(0.0f, 0.0f, getSize().x, getSize().y);
//shader.use();
attribute_coord = shader.getAttribute("coord");
uniform_tex = shader.getUniform("tex");
uniform_color = shader.getUniform("color");
//glUniformMatrix4fv(glGetUniformLocation(shader.ID, "projection"), 1, GL_FALSE, projection.ptr());
if(attribute_coord == -1 || uniform_tex == -1 || uniform_color == -1)
return;
glGenBuffers(1, &VBO);
}
void display() {
shader.use();
float scaleX = 2.f / getSize().x;
float scaleY = 2.f / getSize().y;
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
/* Enable blending, necessary for our alpha texture */
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
FT_Set_Pixel_Sizes(face, 0, 48);
GLfloat black[4] = { 0, 0, 0, 1 };
glUniform4fv(uniform_color, 1, black);
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);
RenderText("WHATS BOPPIN muth ~~~ niger ~~~ aphuqqa____?", 0.f, 0.f, scaleX, JGL::Colors::Black);
JGL::J2D::FillRect2D(JGL::Colors::Greens::DarkOliveGreen, {0, 0}, {128, 128});
JGL::J2D::FillRect2D(JGL::Colors::Greens::DarkSeaGreen, {0, 0}, {64, 64});
JGL::J2D::FillRect2D(JGL::Colors::Greens::DarkGreen, {0, 0}, {32, 32});
JGL::J2D::FillRect2D(JGL::Colors::Greens::Chartreuse, {0, 0}, {1, 1});
JGL::J2D::FillRect2D(JGL::Colors::Yellows::Moccasin, {-128, -128}, {128, 128});
JGL::J2D::FillRect2D(JGL::Colors::Yellows::PeachPuff, {-64, -64}, {64, 64});
JGL::J2D::FillRect2D(JGL::Colors::Yellows::LemonChiffon, {-32, -32}, {32, 32});
JGL::J2D::FillRect2D(JGL::Colors::Yellows::Khaki, {-1, -1}, {1, 1});
//glFlush(); // Render now
}
void RenderText(std::string text, float x, float y, float scale, JGL::Color3 color)
{
const char* p;
// TODO: implement shader.pushColor();
shader.use();
GLuint tex;
FT_GlyphSlot g = face->glyph;
//glUniform3f(glGetUniformLocation(shader.ID, "textColor"), color.r/255.f, color.g/255.f, color.b/255.f);
glActiveTexture(GL_TEXTURE0);
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glUniform1i(uniform_tex, 0);
// We require 1-byte alignment when uploading texture data
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Clamping to edges is important to prevent artifacts when scaling
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
// Linear filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glEnableVertexAttribArray(attribute_coord);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glVertexAttribPointer(attribute_coord, 4, GL_FLOAT, GL_FALSE, 0, 0);
// Loop through all characters
for (p = text.c_str(); *p; p++)
{
if (FT_Load_Char(face, *p, FT_LOAD_RENDER))
continue;
// Upload the "bitmap" which contains an 8-bit grayscale image, as an alpha texture
glTexImage2D(
GL_TEXTURE_2D,
0,
GL_ALPHA,
g->bitmap.width,
g->bitmap.rows,
0,
GL_ALPHA,
GL_UNSIGNED_BYTE,
g->bitmap.buffer
);
// Calculate the vertex and texture coordinates
float x2 = x + g->bitmap_left * scale;
float y2 = -y - g->bitmap_top * scale;
float w = g->bitmap.width * scale;
float h = g->bitmap.rows * scale;
point box[4] = {
{x2, -y2, 0, 0},
{x2 + w, -y2, 1, 0},
{x2, -y2 - h, 0, 1},
{x2 + w, -y2 - h, 1, 1},
};
// Draw the character on the screen
glBufferData(GL_ARRAY_BUFFER, sizeof box, box, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
// Advance the cursor to the start of the next character */
x += (g->advance.x >> 6) * scale;
y += (g->advance.y >> 6) * scale;
}
glDisableVertexAttribArray(attribute_coord);
glDeleteTextures(1, &tex);
/*
// 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;
float w = ch.Size.x * scale;
float h = ch.Size.y * scale;
char valu = *c;
if (valu != ' ')
{
std::cout << valu << ", " << xpos << ", " << ypos << ", " << w << "," << h << std::endl;
JGL::J2D::FillRect2D({valu, 0, valu}, {xpos, ypos}, {w, h});
}
float fxpos = xpos / getSize().x;
float fypos = ypos / getSize().y;
float fw = w / getSize().x;
float fh = h / getSize().y;
float vertices[6][4] = {
{fxpos, fypos + fh, 0.0f, 0.0f},
{fxpos, fypos, 0.0f, 1.0f},
{fxpos + fw, fypos, 1.0f, 1.0f},
{fxpos, fypos + fh, 0.0f, 0.0f},
{fxpos + fw, fypos, 1.0f, 1.0f},
{fxpos + fw, fypos + fh, 1.0f, 0.0f}
};
JGL::InitTextEngine();
}
// 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 display()
{
glClear(GL_COLOR_BUFFER_BIT);
JGL::RenderText("WHATS BOPPIN muth ~~~ niger ~~~ aphuqqa____?", 0.f, -100.f, 1.f);
}
void OnRefresh(float elapsed) override

View File

@@ -1,10 +1,20 @@
//
// Created by dawsh on 1/17/24.
//
#include <glad/glad.h>
#include <JGL/JGL.h>
#include <GL/glut.h>
#include "J3ML/LinearAlgebra/Transform2D.h"
#include <rewindow/types/window.h>
#include <freetype2/ft2build.h>
#include FT_FREETYPE_H
#include <iostream>
GLuint program;
GLuint texture;
namespace JGL
{
Vector2 ScreenToViewport(const Vector2 &v) {
@@ -28,6 +38,80 @@ namespace JGL
};
}
FT_Face face;
FT_Library ft;
bool InitTextEngine() {
if (FT_Init_FreeType(&ft))
{
std::cout << "Error::FREETYPE: " << std::endl;
return false;
}
if (FT_New_Face(ft, "content/FreeSans.ttf", 0, &face))
{
std::cout << "Error::FREETYPE: Failed to load font!" << std::endl;
return false;
}
FT_Set_Pixel_Sizes(face, 0, 48);
return true;
}
void RenderText(std::string text, float x, float y, float scale) {
glUseProgram(0); // Fixed-function pipeline.
glColor3f(1.0f, 1.0f, 1.0f);
const char* c;
for (c = text.c_str(); *c; c++)
{
if (FT_Load_Char(face, *c, FT_LOAD_RENDER))
continue;
FT_GlyphSlot g = face->glyph;
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, g->bitmap.width, g->bitmap.rows, 0, GL_RED, GL_UNSIGNED_BYTE, g->bitmap.buffer);
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);
float x2 = x + g->bitmap_left * scale;
float y2 = -y - g->bitmap_top * scale; // Adjust y-coordinate
float w = g->bitmap.width * scale;
float h = g->bitmap.rows * scale;
glBegin(GL_TRIANGLES);
glTexCoord2f(0, 0);
glVertex2f(x2, y2);
glTexCoord2f(0, 1);
glVertex2f(x2, y2 + h);
glTexCoord2f(1, 1);
glVertex2f(x2 + w, y2 + h);
glTexCoord2f(0, 0);
glVertex2f(x2, y2);
glTexCoord2f(1, 1);
glVertex2f(x2 + w, y2 + h);
glTexCoord2f(1, 0);
glVertex2f(x2 + w, y2);
glEnd();
x += (g->advance.x >> 6) * scale;
y += (g->advance.y >> 6) * scale;
}
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture
}
namespace J2D
{
void FillRect2D(const Color3 &color, const Vector2 &pos, const Vector2 &size) {