J3D::DrawString is now fast.
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m33s
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m33s
This commit is contained in:
@@ -27,7 +27,7 @@ public:
|
||||
//CachedGlyph(GLuint texture_id, char c);
|
||||
CachedGlyph(char c, std::array<GLfloat, 12> texcoords, float x2o, float y2o, float w, float h, float advX, float advY);
|
||||
char getCharacter();
|
||||
[[nodiscard]] const std::array<GLfloat, 12> getTexCoords() const;
|
||||
[[nodiscard]] std::array<GLfloat, 12> getTexCoords() const;
|
||||
};
|
||||
|
||||
/// Represents a Font object as it exists in the font-cache.
|
||||
|
15
src/JGL.cpp
15
src/JGL.cpp
@@ -629,6 +629,13 @@ namespace JGL {
|
||||
wasVertexArraysEnabled = false,
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
if (!glIsEnabled(GL_TEXTURE_COORD_ARRAY))
|
||||
wasTextureCoordArrayEnabled = false,
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
else
|
||||
wasTextureCoordArrayEnabled = true;
|
||||
|
||||
|
||||
wasTexture2DEnabled = true;
|
||||
if (!glIsEnabled(GL_TEXTURE_2D))
|
||||
wasTexture2DEnabled = false,
|
||||
@@ -639,13 +646,12 @@ namespace JGL {
|
||||
wasCullFaceEnabled = true,
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
wasBlendEnabled = true;
|
||||
if (!glIsEnabled(GL_BLEND))
|
||||
wasBlendEnabled = false,
|
||||
glEnable(GL_BLEND),
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
|
||||
else
|
||||
wasBlendEnabled = true;
|
||||
|
||||
if (!inJ2D)
|
||||
inJ3D = true;
|
||||
@@ -669,6 +675,9 @@ namespace JGL {
|
||||
if (wasCullFaceEnabled)
|
||||
glEnable(GL_CULL_FACE);
|
||||
|
||||
if (!wasTextureCoordArrayEnabled)
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
//Put the draw color back how it was before.
|
||||
glColor4fv(oldColor);
|
||||
inJ3D = false;
|
||||
|
@@ -23,92 +23,92 @@ namespace JGL {
|
||||
fontCache.purgeCache();
|
||||
}
|
||||
|
||||
void J2D::DrawString(const Color4& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font) {
|
||||
glUseProgram(0); // Fixed-function pipeline.
|
||||
CachedFont* CacheFont(const Font& font, u32 size) {
|
||||
CachedFont* cachedFont;
|
||||
FT_Set_Pixel_Sizes(font.face, 0, size);
|
||||
jlog::Debug("Caching font data...");
|
||||
GLuint texture_id;
|
||||
glGenTextures(1, &texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
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);
|
||||
|
||||
// Offset by height to render at "correct" location.
|
||||
y += size;
|
||||
GLsizei width = 0;
|
||||
GLsizei max_height = 0;
|
||||
FT_ULong charcode;
|
||||
FT_UInt gindex;
|
||||
|
||||
CachedFont* cachedFont = fontCache.getFont(size, font.index);
|
||||
//We have to loop over the available glyphs twice as we need the
|
||||
//final width and height of the texture_handle before we can construct it
|
||||
//and subsequently upload the glyph data.
|
||||
charcode = FT_Get_First_Char(font.face, &gindex);
|
||||
//Strings are char-based so we only handle charcodes within the extended ASCII range.
|
||||
while (gindex != 0 && charcode < 255) {
|
||||
if (FT_Load_Char(font.face, charcode, FT_LOAD_RENDER))
|
||||
std::cout << "Error::FREETYPE: Failed to load charcode: " << charcode << std::endl;
|
||||
|
||||
if (font.face == nullptr)
|
||||
return;
|
||||
FT_GlyphSlot g = font.face->glyph;
|
||||
width += g->bitmap.width;
|
||||
max_height = std::max(max_height, (GLsizei) g->bitmap.rows);
|
||||
charcode = FT_Get_Next_Char(font.face, charcode, &gindex);
|
||||
}
|
||||
|
||||
//If the font doesn't exist in the cache yet.
|
||||
if (!cachedFont) {
|
||||
FT_Set_Pixel_Sizes(font.face, 0, size);
|
||||
jlog::Debug("Caching font data...");
|
||||
GLuint texture_id;
|
||||
glGenTextures(1, &texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, texture_id);
|
||||
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);
|
||||
fontCache.newFont(texture_id, width, max_height, size, font.index);
|
||||
cachedFont = fontCache.getFont(size, font.index);
|
||||
|
||||
GLsizei width = 0;
|
||||
GLsizei max_height = 0;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, max_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
FT_ULong charcode;
|
||||
FT_UInt gindex;
|
||||
GLsizei xoffset = 0;
|
||||
|
||||
//We have to loop over the available glyphs twice as we need the
|
||||
//final width and height of the texture_handle before we can construct it
|
||||
//and subsequently upload the glyph data.
|
||||
charcode = FT_Get_First_Char(font.face, &gindex);
|
||||
while (gindex != 0 && charcode < 255) {
|
||||
if (FT_Load_Char(font.face, charcode, FT_LOAD_RENDER))
|
||||
std::cout << "Error::FREETYPE: Failed to load charcode: " << charcode << std::endl;
|
||||
|
||||
charcode = FT_Get_First_Char(font.face, &gindex);
|
||||
//Strings are char-based so we only handle charcodes within the extended ASCII range.
|
||||
while (gindex != 0 && charcode < 255) {
|
||||
if (FT_Load_Char(font.face, charcode, FT_LOAD_RENDER))
|
||||
std::cout << "Error::FREETYPE: Failed to load charcode: " << charcode << std::endl;
|
||||
FT_GlyphSlot g = font.face->glyph;
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, 0, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
|
||||
|
||||
FT_GlyphSlot g = font.face->glyph;
|
||||
width += g->bitmap.width;
|
||||
max_height = std::max(max_height, (GLsizei) g->bitmap.rows);
|
||||
charcode = FT_Get_Next_Char(font.face, charcode, &gindex);
|
||||
}
|
||||
GLfloat u0 = (GLfloat)xoffset / cachedFont->getTextureWidth();
|
||||
GLfloat u1 = u0 + (GLfloat)g->bitmap.width / cachedFont->getTextureWidth();
|
||||
|
||||
fontCache.newFont(texture_id, width, max_height, size, font.index);
|
||||
cachedFont = fontCache.getFont(size, font.index);
|
||||
GLfloat v0 = 0.0f;
|
||||
GLfloat v1 = (GLfloat)g->bitmap.rows / cachedFont->getTextureHeight();
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, max_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, nullptr);
|
||||
|
||||
GLsizei xoffset = 0;
|
||||
|
||||
charcode = FT_Get_First_Char(font.face, &gindex);
|
||||
while (gindex != 0 && charcode < 255) {
|
||||
if (FT_Load_Char(font.face, charcode, FT_LOAD_RENDER))
|
||||
std::cout << "Error::FREETYPE: Failed to load charcode: " << charcode << std::endl;
|
||||
|
||||
FT_GlyphSlot g = font.face->glyph;
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, xoffset, 0, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer);
|
||||
|
||||
GLfloat u0 = (GLfloat)xoffset / cachedFont->getTextureWidth();
|
||||
GLfloat u1 = u0 + (GLfloat)g->bitmap.width / cachedFont->getTextureWidth();
|
||||
|
||||
GLfloat v0 = 0.0f;
|
||||
GLfloat v1 = (GLfloat)g->bitmap.rows / cachedFont->getTextureHeight();
|
||||
|
||||
std::array<GLfloat, 12> texcoords = {
|
||||
std::array<GLfloat, 12> texcoords = {
|
||||
u0, v0,
|
||||
u0, v1,
|
||||
u1, v1,
|
||||
u0, v0,
|
||||
u1, v1,
|
||||
u1, v0
|
||||
};
|
||||
};
|
||||
|
||||
cachedFont->appendGlyph(new CachedGlyph((char)charcode, texcoords, g->bitmap_left, g->bitmap_top, g->bitmap.width, g->bitmap.rows, (g->advance.x >> 6), (g->advance.y >> 6)));
|
||||
cachedFont->appendGlyph(new CachedGlyph((char)charcode, texcoords, g->bitmap_left, g->bitmap_top, g->bitmap.width, g->bitmap.rows, (g->advance.x >> 6), (g->advance.y >> 6)));
|
||||
|
||||
xoffset += g->bitmap.width;
|
||||
charcode = FT_Get_Next_Char(font.face, charcode, &gindex);
|
||||
}
|
||||
xoffset += g->bitmap.width;
|
||||
charcode = FT_Get_Next_Char(font.face, charcode, &gindex);
|
||||
}
|
||||
return cachedFont;
|
||||
}
|
||||
|
||||
void J2D::DrawString(const Color4& color, const std::string& text, float x, float y, float scale, u32 size, const Font& font) {
|
||||
// Offset by height to render at "correct" location.
|
||||
y += size;
|
||||
|
||||
CachedFont* cachedFont = fontCache.getFont(size, font.index);
|
||||
|
||||
if (font.face == nullptr)
|
||||
jlog::Fatal("Drawing a string with an uninitialized font?");
|
||||
|
||||
//If the font doesn't exist in the cache yet.
|
||||
if (!cachedFont)
|
||||
cachedFont = CacheFont(font, size);
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
|
||||
//Texture parameters are restored when the texture_handle is bound
|
||||
glBindTexture(GL_TEXTURE_2D, *cachedFont->getTexture());
|
||||
|
||||
@@ -136,34 +136,38 @@ namespace JGL {
|
||||
x2 + w, y2 + h,
|
||||
x2 + w, y2
|
||||
};
|
||||
|
||||
auto glyph_texcoords = glyph->getTexCoords();
|
||||
vertices[i] = glyph_vertices;
|
||||
texcoords[i] = glyph_texcoords;
|
||||
}
|
||||
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(GLfloat) * 2, vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(GLfloat) * 2, texcoords.data());
|
||||
glVertexPointer(2, GL_FLOAT, sizeof(Vector2), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), texcoords.data());
|
||||
glDrawArrays(GL_TRIANGLES, 0, (int) vertices.size() * 6);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glColor4f(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
void J3D::DrawString(const Color4& color, const std::string& text, const Vector3& pos, float scale, u32 size, const Font& font, const EulerAngle& angle, bool draw_back_face) {
|
||||
//TODO figure out what the scale should actually be mathematically.
|
||||
// TODO: Determine the proper scale factor mathematically
|
||||
scale = scale * 0.002f;
|
||||
scale = -scale;
|
||||
|
||||
float x = pos.x;
|
||||
float y = pos.y;
|
||||
float z = pos.z;
|
||||
std::vector<GLuint> textures(text.length());
|
||||
glUseProgram(0); // Fixed-function pipeline.
|
||||
glColor4ubv(color.ptr());
|
||||
|
||||
CachedFont* cachedFont = fontCache.getFont(size, font.index);
|
||||
if (font.face == nullptr)
|
||||
throw std::runtime_error("FreeType font face is null.");
|
||||
jlog::Fatal("Drawing a string with an uninitialized font?");
|
||||
|
||||
FT_Set_Pixel_Sizes(font.face, 0, size);
|
||||
if (!cachedFont)
|
||||
cachedFont = CacheFont(font, size);
|
||||
|
||||
glColor4ubv(color.ptr());
|
||||
glBindTexture(GL_TEXTURE_2D, *cachedFont->getTexture());
|
||||
|
||||
std::vector<std::array<GLfloat, 18>> vertices(text.size());
|
||||
std::vector<std::array<GLfloat, 12>> texcoords(text.size());
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(x, y, z);
|
||||
@@ -172,66 +176,42 @@ namespace JGL {
|
||||
glRotatef(angle.roll, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
x = y = z = 0;
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
CachedGlyph* glyph = cachedFont->getGlyph(text[i]);
|
||||
|
||||
for (int i = 0; i < text.length(); i++)
|
||||
{
|
||||
if (FT_Load_Char(font.face, text.c_str()[i], FT_LOAD_RENDER))
|
||||
continue;
|
||||
float x2 = x + glyph->x2offset * scale;
|
||||
float y2 = y - glyph->y2offset * scale;
|
||||
float w = glyph->w * scale;
|
||||
float h = glyph->h * scale;
|
||||
|
||||
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);
|
||||
std::array<GLfloat, 18> glyph_vertices = {
|
||||
x2, y2, z,
|
||||
x2, y2 + h, z,
|
||||
x2 + w, y2 + h, z,
|
||||
x2, y2, z,
|
||||
x2 + w, y2 + h, z,
|
||||
x2 + w, y2, z
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
if (!draw_back_face)
|
||||
glEnable(GL_CULL_FACE),
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
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();
|
||||
|
||||
if (!draw_back_face)
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
x += (g->advance.x >> 6) * scale;
|
||||
y += (g->advance.y >> 6) * scale;
|
||||
vertices[i] = glyph_vertices;
|
||||
texcoords[i] = glyph->getTexCoords();
|
||||
x += glyph->advanceX * scale;
|
||||
y += glyph->advanceY * scale;
|
||||
}
|
||||
|
||||
for (unsigned int& texture : textures)
|
||||
glDeleteTextures(1, &texture);
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(Vector3), vertices.data());
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(Vector2), texcoords.data());
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0); // Unbind texture_handle
|
||||
if (!draw_back_face)
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, (int) vertices.size() * 6);
|
||||
|
||||
if (!draw_back_face)
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glColor4f(1, 1, 1, 1);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ char CachedGlyph::getCharacter() {
|
||||
return character;
|
||||
}
|
||||
|
||||
const std::array<GLfloat, 12> CachedGlyph::getTexCoords() const {
|
||||
std::array<GLfloat, 12> CachedGlyph::getTexCoords() const {
|
||||
return texcoords;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user