Refactor & Fix inverted text & More
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m37s

This commit is contained in:
2024-07-07 17:10:51 -04:00
parent c62b58aa16
commit 0914b496e7
4 changed files with 484 additions and 453 deletions

View File

@@ -2,378 +2,170 @@
// Created by dawsh on 1/17/24.
//
#include <vector>
#include <glad/glad.h>
#include <JGL/JGL.h>
#include <glad/glad.h>
#include <JGL/Color3.h>
#if __linux__
#include <freetype2/ft2build.h>
#include FT_FREETYPE_H
#endif
#if _WIN32
#include <ft2build.h>
#include FT_FREETYPE_H
#endif
GLuint program;
namespace JGL
{
FT_Library ft;
struct Font {
int index = 0;
FT_Face face;
};
std::vector<Font> faces;
bool wasDepthTest = false;
namespace JGL {
using namespace J3ML;
bool InitTextEngine() {
if (FT_Init_FreeType(&ft))
return true;
return false;
Vector2 wS;
bool Update(const Vector2& window_size) {
wS = window_size;
return JGL::InitTextEngine();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
int LoadFont(const std::string &font_path) {
if (ft == nullptr)
return -1;
void J2D::Begin() {
glEnable(GL_TEXTURE_2D);
// Switch to orthographic projection
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, wS.x, wS.y, 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
Font font;
if (FT_New_Face(ft, font_path.c_str(), 0, &font.face)) {
std::cout << "Error::FREETYPE: Failed to load font!" << std::endl;
return -1;
}
unsigned int newIndex = 0;
for (const auto& f : faces)
if (f.index >= newIndex)
newIndex = f.index + 1;
font.index = newIndex;
faces.push_back(font);
std::cout << "Loaded font from " << font_path << " with index " << newIndex << std::endl;
return newIndex;
wasDepthTest = false;
if (glIsEnabled(GL_DEPTH_TEST))
wasDepthTest = true,
glDisable(GL_DEPTH_TEST);
}
void UnloadFont(int font_index) {
for (int i = 0; i < faces.size(); i++)
if (faces[i].index == font_index)
FT_Done_Face(faces[i].face),
faces.erase(faces.begin() + i);
void J2D::End() {
//Change back to the previous projection (The 3D one in Re3D's case.
glDisable(GL_TEXTURE_2D);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
if (wasDepthTest)
glEnable(GL_DEPTH_TEST);
}
namespace J2D {
void FillRect2D(const Color3 &color, const Vector2 &pos, const Vector2 &size) {
auto vp_pos = pos;
auto vp_size = size;
glBegin(GL_QUADS);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glVertex2f(vp_pos.x, vp_pos.y);
glVertex2f(vp_pos.x, vp_pos.y + vp_size.y);
glVertex2f(vp_pos.x + vp_size.x, vp_pos.y + vp_size.y);
glVertex2f(vp_pos.x + vp_size.x, vp_pos.y);
glEnd();
}
void OutlineRect2D(const Color3 &color, const Vector2 &pos, const Vector2 &size, float thickness) {
auto vp_pos = pos;
auto vp_size = size;
glBegin(GL_LINE_LOOP);
glLineWidth(thickness);
glColor3f(color.r, color.g, color.b);
glVertex2f(vp_pos.x, vp_pos.y);
glVertex2f(vp_pos.x, vp_pos.y + vp_size.y);
glVertex2f(vp_pos.x + vp_size.x, vp_pos.y + vp_size.y);
glVertex2f(vp_pos.x + vp_size.x, vp_pos.y);
glEnd();
}
void DrawLine2D(const Color3 &color, const Vector2 &A, const Vector2 &B, float thickness) {
auto vp_a = A;
auto vp_b = B;
glBegin(GL_LINES);
glLineWidth(thickness);
glColor3f(color.r, color.g, color.b);
glVertex2f(vp_a.x, vp_a.y);
glVertex2f(vp_b.x, vp_b.y);
glEnd();
}
void DrawLine2D(const Color3 &color, float x, float y, float w, float h, float thickness) {
DrawLine2D(color, {x, y}, {w, h}, thickness);
}
void DrawPixel2D(const Color3 &color, float x, float y) {
DrawPixel2D(color, {x, y});
}
void DrawPixel2D(const Color3 &color, const Vector2 &coordinates) {
auto vp_pos = coordinates;
glBegin(GL_POINT);
glColor3f(color.r, color.g, color.b);
glVertex2f(vp_pos.x, vp_pos.y);
glEnd();
}
void
OutlineCircle2D(const Color3 &color, const Vector2 &center, float radius, int subdivisions, float thickness) {
glBegin(GL_LINE_LOOP);
GLfloat angle;
glColor3f(color.r, color.g, color.b);
float step = (2.f * M_PI) / (float) subdivisions;
for (angle = 0.0f; angle < (2.f * M_PI); angle += step) {
GLfloat x = radius * sin(angle);
GLfloat y = radius * cos(angle);
x += center.x;
y += center.y;
glVertex2f(x, y);
}
glEnd();
}
void FillCircle2D(const Color3 &color, const Vector2 &center, float radius, int subdivisions) {
glBegin(GL_POLYGON);
GLfloat angle;
glColor3f(color.r, color.g, color.b);
float step = (2.f * M_PI) / (float) subdivisions;
for (angle = 0.0f; angle < (2.f * M_PI); angle += step) {
GLfloat x = radius * sin(angle);
GLfloat y = radius * cos(angle);
x += center.x;
y += center.y;
glVertex2f(x, y);
}
glEnd();
}
void OutlineTriangle2D(const Color3 &color, const Triangle2D &tri) {
glBegin(GL_LINE_LOOP);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glVertex2f(tri.A.x, tri.A.y);
glVertex2f(tri.B.x, tri.B.y);
glVertex2f(tri.C.x, tri.C.y);
glEnd();
}
void FillTriangle2D(const Color3 &color, const Triangle2D &tri) {
glBegin(GL_LINE_LOOP);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glVertex2f(tri.A.x, tri.A.y);
glVertex2f(tri.B.x, tri.B.y);
glVertex2f(tri.C.x, tri.C.y);
glEnd();
}
void DrawString2D(const Color3& color, std::string text, float x, float y, float scale, u32 size, unsigned int font_index) {
glUseProgram(0); // Fixed-function pipeline.
Font font{};
CachedFont* cachedFont = fontCache.getFont(size, font_index);
//If the font doesn't exist in the cache yet.
if (!cachedFont) {
fontCache.newFont(size, font_index);
cachedFont = fontCache.getFont(size, font_index);
}
//Set up the regular font.
for (const auto& f : faces)
if (f.index == font_index)
font = f;
if (font.face == nullptr)
return;
GLfloat currentColor[4];
glGetFloatv(GL_CURRENT_COLOR, currentColor);
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, 1.0f);
FT_Set_Pixel_Sizes(font.face, 0, size);
std::vector<GLuint> textures(text.length());
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
//For each character
for (int i = 0; i < text.length(); i++) {
float x2, y2, w, h;
//If the font is in the cache already.
if (cachedFont->getGlyph(text.c_str()[i])) {
CachedGlyph* glyph = cachedFont->getGlyph(text.c_str()[i]);
glBindTexture(GL_TEXTURE_2D, *glyph->getTexture());
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
x2 = x + glyph->x2offset * scale;
y2 = -y - glyph->y2offset * scale; // Adjust y-coordinate
w = glyph->w * scale;
h = glyph->h * scale;
x += glyph->advanceX * scale;
y += glyph->advanceY * scale;
} else {
if (FT_Load_Char(font.face, text.c_str()[i], FT_LOAD_RENDER))
continue;
FT_GlyphSlot g = font.face->glyph;
glGenTextures(1, &textures.at(i));
glBindTexture(GL_TEXTURE_2D, textures[i]);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, g->bitmap.width, g->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
x2 = x + g->bitmap_left * scale;
y2 = -y - g->bitmap_top * scale; // Adjust y-coordinate
w = g->bitmap.width * scale;
h = g->bitmap.rows * scale;
x += (g->advance.x >> 6) * scale;
y += (g->advance.y >> 6) * scale;
cachedFont->appendGlyph(new CachedGlyph(textures.at(i), text.c_str()[i], g->bitmap_left, g->bitmap_top, g->bitmap.width, g->bitmap.rows, (g->advance.x >> 6), (g->advance.y >> 6)));
}
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();
}
//for (unsigned int& texture : textures)
//glDeleteTextures(1, &texture);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture
glColor4f(currentColor[0], currentColor[1], currentColor[2], currentColor[3]); //Set draw color back to whatever it was before.
}
void J2D::FillRect(const Color3 &color, const Vector2 &pos, const Vector2 &size) {
auto vp_pos = pos;
auto vp_size = size;
glBegin(GL_QUADS);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glVertex2f(vp_pos.x, vp_pos.y);
glVertex2f(vp_pos.x, vp_pos.y + vp_size.y);
glVertex2f(vp_pos.x + vp_size.x, vp_pos.y + vp_size.y);
glVertex2f(vp_pos.x + vp_size.x, vp_pos.y);
glEnd();
}
namespace J3D
{
void DrawLine3D(const Color3& color, const Vector3& A, const Vector3& B, float thickness)
{
glBegin(GL_LINES);
glLineWidth(thickness);
glColor3f(color.r/255.f, color.g/255.f, color.b/255.f);
glVertex3f(A.x, A.y, A.z);
glVertex3f(B.x, B.y, B.z);
glEnd();
}
void DrawString3D(const Color3& color, const std::string& text, const Vector3& pos, float scale, u32 size, unsigned int font_index)
{
float x = pos.x;
float y = pos.y;
float z = pos.z;
GLfloat currentColor[4];
std::vector<GLuint> textures(text.length());;
glGetFloatv(GL_CURRENT_COLOR, currentColor);
glUseProgram(0); // Fixed-function pipeline.
glColor4f(color.r, color.g, color.b, 1.0f);
Font font;
for (auto& f : faces)
if (f.index == font_index)
font = f;
if (font.face == NULL) {
std::cout << "null font" << std::endl;
return;
}
FT_Set_Pixel_Sizes(font.face, 0, size);
//for (c = text.c_str(); *c; c++)
for (int i = 0; i < text.length(); i++)
{
if (FT_Load_Char(font.face, text.c_str()[i], FT_LOAD_RENDER))
continue;
FT_GlyphSlot g = font.face->glyph;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &textures.at(i));
glBindTexture(GL_TEXTURE_2D, textures[i]);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, g->bitmap.width, g->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
float x2 = x + g->bitmap_left * scale;
float y2 = -y - g->bitmap_top * scale; // Adjust y-coordinate
float z2 = z;
float w = g->bitmap.width * scale;
float h = g->bitmap.rows * scale;
glBegin(GL_TRIANGLES);
glTexCoord2f(0, 0);
glVertex3f(x2, y2, z2);
glTexCoord2f(0, 1);
glVertex3f(x2, y2 + h, z2);
glTexCoord2f(1, 1);
glVertex3f(x2 + w, y2 + h, z2);
glTexCoord2f(0, 0);
glVertex3f(x2, y2, z2);
glTexCoord2f(1, 1);
glVertex3f(x2 + w, y2 + h, z2);
glTexCoord2f(1, 0);
glVertex3f(x2 + w, y2, z2);
glEnd();
x += (g->advance.x >> 6) * scale;
y += (g->advance.y >> 6) * scale;
}
for (unsigned int& texture : textures)
glDeleteTextures(1, &texture);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture
glColor4f(currentColor[0], currentColor[1], currentColor[2], currentColor[3]); //Set draw color back to whatever it was before.
}
void J2D::OutlineRect(const Color3 &color, const Vector2 &pos, const Vector2 &size, float thickness) {
auto vp_pos = pos;
auto vp_size = size;
glBegin(GL_LINE_LOOP);
glLineWidth(thickness);
glColor3f(color.r, color.g, color.b);
glVertex2f(vp_pos.x, vp_pos.y);
glVertex2f(vp_pos.x, vp_pos.y + vp_size.y);
glVertex2f(vp_pos.x + vp_size.x, vp_pos.y + vp_size.y);
glVertex2f(vp_pos.x + vp_size.x, vp_pos.y);
glEnd();
}
}
void J2D::DrawLine(const Color3 &color, const Vector2 &A, const Vector2 &B, float thickness) {
auto vp_a = A;
auto vp_b = B;
glBegin(GL_LINES);
glLineWidth(thickness);
glColor3f(color.r, color.g, color.b);
glVertex2f(vp_a.x, vp_a.y);
glVertex2f(vp_b.x, vp_b.y);
glEnd();
}
void J2D::DrawLine(const Color3 &color, float x, float y, float w, float h, float thickness) {
DrawLine(color, {x, y}, {w, h}, thickness);
}
void J2D::DrawPixel(const Color3 &color, float x, float y) {
DrawPixel(color, {x, y});
}
void J2D::DrawPixel(const Color3 &color, const Vector2 &coordinates) {
auto vp_pos = coordinates;
glBegin(GL_POINT);
glColor3f(color.r, color.g, color.b);
glVertex2f(vp_pos.x, vp_pos.y);
glEnd();
}
void J2D::OutlineCircle(const Color3 &color, const Vector2 &center, float radius, int subdivisions, float thickness) {
glBegin(GL_LINE_LOOP);
GLfloat angle;
glColor3f(color.r, color.g, color.b);
float step = (2.f * M_PI) / (float) subdivisions;
for (angle = 0.0f; angle < (2.f * M_PI); angle += step) {
GLfloat x = radius * sin(angle);
GLfloat y = radius * cos(angle);
x += center.x;
y += center.y;
glVertex2f(x, y);
}
glEnd();
}
void J2D::FillCircle(const Color3 &color, const Vector2 &center, float radius, int subdivisions) {
glBegin(GL_POLYGON);
GLfloat angle;
glColor3f(color.r, color.g, color.b);
float step = (2.f * M_PI) / (float) subdivisions;
for (angle = 0.0f; angle < (2.f * M_PI); angle += step) {
GLfloat x = radius * sin(angle);
GLfloat y = radius * cos(angle);
x += center.x;
y += center.y;
glVertex2f(x, y);
}
glEnd();
}
void J2D::OutlineTriangle(const Color3 &color, const Triangle2D &tri) {
glBegin(GL_LINE_LOOP);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glVertex2f(tri.A.x, tri.A.y);
glVertex2f(tri.B.x, tri.B.y);
glVertex2f(tri.C.x, tri.C.y);
glEnd();
}
void J2D::FillTriangle(const Color3 &color, const Triangle2D &tri) {
glBegin(GL_LINE_LOOP);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glVertex2f(tri.A.x, tri.A.y);
glVertex2f(tri.B.x, tri.B.y);
glVertex2f(tri.C.x, tri.C.y);
glEnd();
}
void J3D::Begin() {
glEnable(GL_TEXTURE_2D);
wasDepthTest = false;
if (glIsEnabled(GL_DEPTH_TEST))
wasDepthTest = true,
glDisable(GL_DEPTH_TEST);
}
void J3D::End() {
glDisable(GL_TEXTURE_2D);
if (wasDepthTest)
glEnable(GL_DEPTH_TEST);
}
void J3D::DrawLine(const Color3 &color, const Vector3 &A, const Vector3 &B, float thickness) {
glBegin(GL_LINES);
glLineWidth(thickness);
glColor3f(color.r / 255.f, color.g / 255.f, color.b / 255.f);
glVertex3f(A.x, A.y, A.z);
glVertex3f(B.x, B.y, B.z);
glEnd();
}
}

245
src/JGL/TextRendering.cpp Normal file
View File

@@ -0,0 +1,245 @@
#include <JGL/JGL.h>
#if __linux__
#include <freetype2/ft2build.h>
#include FT_FREETYPE_H
#endif
#if _WIN32
#include <ft2build.h>
#include FT_FREETYPE_H
#endif
namespace JGL {
FT_Library ft;
struct Font {
int index = 0;
FT_Face face;
};
std::vector<Font> faces;
int LoadFont(const std::string &font_path) {
if (ft == nullptr)
return -1;
Font font;
if (FT_New_Face(ft, font_path.c_str(), 0, &font.face)) {
std::cout << "Error::FREETYPE: Failed to load font!" << std::endl;
return -1;
}
unsigned int newIndex = 0;
for (const auto& f : faces)
if (f.index >= newIndex)
newIndex = f.index + 1;
font.index = newIndex;
faces.push_back(font);
std::cout << "Loaded font from " << font_path << " with index " << newIndex << std::endl;
return newIndex;
}
bool InitTextEngine() {
if (FT_Init_FreeType(&ft))
return true;
return false;
}
void UnloadFont(int font_index) {
for (int i = 0; i < faces.size(); i++)
if (faces[i].index == font_index)
FT_Done_Face(faces[i].face),
faces.erase(faces.begin() + i);
}
FontCache fontCache;
void J2D::DrawString(const Color3& color, std::string text, float x, float y, float scale, u32 size, unsigned int font_index) {
glUseProgram(0); // Fixed-function pipeline.
Font font{};
CachedFont* cachedFont = fontCache.getFont(size, font_index);
//If the font doesn't exist in the cache yet.
if (!cachedFont) {
fontCache.newFont(size, font_index);
cachedFont = fontCache.getFont(size, font_index);
}
//Set up the regular font.
for (const auto& f : faces)
if (f.index == font_index)
font = f;
if (font.face == nullptr)
return;
GLfloat currentColor[4];
glGetFloatv(GL_CURRENT_COLOR, currentColor);
glColor4f(color.r / 255.f, color.g / 255.f, color.b / 255.f, 1.0f);
FT_Set_Pixel_Sizes(font.face, 0, size);
std::vector<GLuint> textures(text.length());
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_TEXTURE_2D);
//For each character
for (int i = 0; i < text.length(); i++) {
float x2, y2, w, h;
//If the font is in the cache already.
if (cachedFont->getGlyph(text.c_str()[i])) {
CachedGlyph* glyph = cachedFont->getGlyph(text.c_str()[i]);
glBindTexture(GL_TEXTURE_2D, *glyph->getTexture());
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
x2 = x + glyph->x2offset * scale;
y2 = -y - glyph->y2offset * scale; // Adjust y-coordinate
w = glyph->w * scale;
h = glyph->h * scale;
x += glyph->advanceX * scale;
y += glyph->advanceY * scale;
} else {
if (FT_Load_Char(font.face, text.c_str()[i], FT_LOAD_RENDER))
continue;
FT_GlyphSlot g = font.face->glyph;
glGenTextures(1, &textures.at(i));
glBindTexture(GL_TEXTURE_2D, textures[i]);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, g->bitmap.width, g->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
x2 = x + g->bitmap_left * scale;
y2 = -y - g->bitmap_top * scale; // Adjust y-coordinate
w = g->bitmap.width * scale;
h = g->bitmap.rows * scale;
x += (g->advance.x >> 6) * scale;
y += (g->advance.y >> 6) * scale;
cachedFont->appendGlyph(new CachedGlyph(textures.at(i), text.c_str()[i], g->bitmap_left, g->bitmap_top, g->bitmap.width, g->bitmap.rows, (g->advance.x >> 6), (g->advance.y >> 6)));
}
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();
}
//for (unsigned int& texture : textures)
//glDeleteTextures(1, &texture);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture
glColor4f(currentColor[0], currentColor[1], currentColor[2], currentColor[3]); //Set draw color back to whatever it was before.
}
void J3D::DrawString(const Color3& color, const std::string& text, const Vector3& pos, float scale, u32 size, unsigned int font_index) {
float x = pos.x;
float y = pos.y;
float z = pos.z;
GLfloat currentColor[4];
std::vector<GLuint> textures(text.length());;
glGetFloatv(GL_CURRENT_COLOR, currentColor);
glUseProgram(0); // Fixed-function pipeline.
glColor4f(color.r, color.g, color.b, 1.0f);
Font font;
for (auto& f : faces)
if (f.index == font_index)
font = f;
if (font.face == NULL) {
std::cout << "null font" << std::endl;
return;
}
FT_Set_Pixel_Sizes(font.face, 0, size);
for (int i = 0; i < text.length(); i++) {
if (FT_Load_Char(font.face, text.c_str()[i], FT_LOAD_RENDER))
continue;
FT_GlyphSlot g = font.face->glyph;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &textures.at(i));
glBindTexture(GL_TEXTURE_2D, textures[i]);
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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, g->bitmap.width, g->bitmap.rows, 0, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
float x2 = x + g->bitmap_left * scale;
float y2 = y + g->bitmap_top * scale; // Adjust y-coordinate to invert the text
float z2 = z;
float w = g->bitmap.width * scale;
float h = g->bitmap.rows * scale;
glBegin(GL_TRIANGLES);
glTexCoord2f(0, 0);
glVertex3f(x2, y2, z2);
glTexCoord2f(0, 1);
glVertex3f(x2, y2 - h, z2);
glTexCoord2f(1, 1);
glVertex3f(x2 + w, y2 - h, z2);
glTexCoord2f(0, 0);
glVertex3f(x2, y2, z2);
glTexCoord2f(1, 1);
glVertex3f(x2 + w, y2 - h, z2);
glTexCoord2f(1, 0);
glVertex3f(x2 + w, y2, z2);
glEnd();
x += (g->advance.x >> 6) * scale;
y += (g->advance.y >> 6) * scale;
}
for (unsigned int& texture : textures)
glDeleteTextures(1, &texture);
glDisable(GL_TEXTURE_2D);
glDisable(GL_BLEND);
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture
glColor4f(currentColor[0], currentColor[1], currentColor[2], currentColor[3]); // Set draw color back to whatever it was before.
}
}