Implement optimizations for 2D text rendering (#23)
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m51s
Some checks failed
Run ReCI Build Test / Explore-Gitea-Actions (push) Failing after 1m51s
The following patches are included: ## J2D: Rewrite text rendering This patch rewrites text rendering for `J2D::DrawString` to now construct a texture atlas for all ASCII-range glyphs in the FT font face, instead of constructing a texture for every glyph. This improves text rendering performance for several reasons: 1. Binding textures is relatively expensive as the GPU is required to do a context switch for internal data like texture parameters, and also cannot optimize for accesses to the same texture across draw calls. This patch removes the need to call `glBindTexture` more than once per call to `J2D::DrawString`. 2. As a consequence of the above, all glyphs for a given string can now be rendered in a single call to `glDrawArrays`. This is done by storing the cached texture coordinates on `CachedGlyph` and constructing a full array of vertices and texture coordinates for the entire string at once, resulting in only /one/ set of client-to-device attribute uploads and only one draw call, instead of being required to upload attribute data for each glyph separately. ## FontCache: Use map for efficient glyph lookup This patch updates `CachedFont` to now use an `std::map` for cached glyphs, instead of an `std::vector`. `std::map` allows O(log n) lookup, whereas `std::vector` only allows O(n) lookup. Note: `std::unordered_map` technically has better lookup complexity here, with amortized O(1) lookup. However, hashmaps have a higher inherent overhead than red-black trees so this would only be viable when going above around 1000 entries, which should never happen here for ASCII glyphs. Co-authored-by: Ori Sky Farrell <ori.sky.farrell+git@gmail.com> Reviewed-on: #23 Co-authored-by: ori_sky <redacted@ori.mx> Co-committed-by: ori_sky <redacted@ori.mx>
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <glad/glad.h>
|
||||
|
||||
@@ -11,33 +13,35 @@ namespace JGL {
|
||||
|
||||
class JGL::CachedGlyph {
|
||||
private:
|
||||
GLuint texture = 0;
|
||||
char character;
|
||||
std::array<GLfloat, 12> texcoords;
|
||||
public:
|
||||
int x2offset = 0, y2offset = 0, w = 0, h = 0;
|
||||
float advanceX = 0, advanceY = 0;
|
||||
|
||||
//CachedGlyph(GLuint texture_id, char c);
|
||||
CachedGlyph(GLuint texture_id, char c, float x2o, float y2o, float w, float h, float advX, float advY);
|
||||
CachedGlyph(char c, std::array<GLfloat, 12> texcoords, float x2o, float y2o, float w, float h, float advX, float advY);
|
||||
char getCharacter();
|
||||
const GLuint* getTexture();
|
||||
const std::array<GLfloat, 12> getTexCoords() const;
|
||||
};
|
||||
|
||||
class JGL::CachedFont {
|
||||
private:
|
||||
std::vector<CachedGlyph*> glyphs{};
|
||||
std::map<char, CachedGlyph*> glyphs;
|
||||
GLuint texture = 0;
|
||||
GLsizei texture_width = 0, texture_height = 0;
|
||||
unsigned int font_size = 0;
|
||||
unsigned int font_index = 0;
|
||||
public:
|
||||
void appendGlyph(CachedGlyph* glyph);
|
||||
void eraseGlyph(CachedGlyph* glyph);
|
||||
void eraseGlyph(char c);
|
||||
void eraseGlyph(GLuint texture_id);
|
||||
unsigned int getFontSize();
|
||||
unsigned int getFontIndex();
|
||||
CachedGlyph* getGlyph(char c);
|
||||
std::vector<CachedGlyph*> getGlyphs();
|
||||
CachedFont(unsigned int font_size, unsigned int font_index);
|
||||
std::map<char, CachedGlyph*> getGlyphs();
|
||||
const GLuint* getTexture();
|
||||
const GLsizei getTextureWidth() const;
|
||||
const GLsizei getTextureHeight() const;
|
||||
CachedFont(GLuint texture_id, GLsizei texture_width, GLsizei texture_height, unsigned int font_size, unsigned int font_index);
|
||||
};
|
||||
|
||||
class JGL::FontCache {
|
||||
@@ -47,7 +51,7 @@ public:
|
||||
std::vector<CachedFont*> getFonts();
|
||||
CachedFont* getFont(unsigned int font_size, unsigned int font_index);
|
||||
void appendFont(CachedFont* font);
|
||||
void newFont(unsigned int font_size, unsigned int font_index);
|
||||
void newFont(GLuint texture_id, GLsizei texture_width, GLsizei texture_height, unsigned int font_size, unsigned int font_index);
|
||||
void eraseFont(CachedFont* font);
|
||||
void purgeCache();
|
||||
};
|
||||
};
|
||||
|
Reference in New Issue
Block a user