From 3ca30721b633ca89c831e50352562647444b4f15 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Mon, 5 Jun 2023 11:49:38 -0700 Subject: [PATCH] TTF Prog --- src/dawn/display/Color.hpp | 25 +- src/dawn/display/font/FontManager.cpp | 9 + src/dawn/display/font/FontManager.hpp | 4 + src/dawn/display/font/NewTrueType.cpp | 68 ++++- src/dawn/display/font/NewTrueType.hpp | 86 +++++- src/dawn/scene/components/ui/UILabelNew.cpp | 256 +++++++++--------- src/dawn/scene/components/ui/UILabelNew.hpp | 48 ++-- .../display/shader/shaders/FontShader.cpp | 31 ++- .../display/shader/shaders/FontShader.hpp | 21 +- src/dawnshared/CMakeLists.txt | 1 + src/dawnshared/util/UsageLock.cpp | 27 ++ src/dawnshared/util/UsageLock.hpp | 39 +++ 12 files changed, 405 insertions(+), 210 deletions(-) create mode 100644 src/dawnshared/util/UsageLock.cpp create mode 100644 src/dawnshared/util/UsageLock.hpp diff --git a/src/dawn/display/Color.hpp b/src/dawn/display/Color.hpp index d3412508..98caeff5 100644 --- a/src/dawn/display/Color.hpp +++ b/src/dawn/display/Color.hpp @@ -53,16 +53,17 @@ namespace Dawn { }; #pragma pack(pop) - #define COLOR_WHITE { 1.0f, 1.0f, 1.0f, 1.0f } - #define COLOR_RED { 1.0f, 0, 0, 1.0f } - #define COLOR_GREEN { 0, 1.0f, 0, 1.0f } - #define COLOR_BLUE { 0, 0, 1.0f, 1.0f } - #define COLOR_BLACK { 0, 0, 0, 1.0f } - #define COLOR_MAGENTA { 1.0f, 0, 1.0f, 1.0f } - #define COLOR_DARK_GREY { 0.19607843137254901961f, 0.19607843137254901961f, 0.19607843137254901961f, 1.0f } - #define COLOR_LIGHT_GREY { 0.8f, 0.8f, 0.8f, 1.0f } - #define COLOR_CORNFLOWER_BLUE { 0.39215686274509803922f, 0.58431372549019607843f, 0.92941176470588235294f, 1.0f } - #define COLOR_WHITE_TRANSPARENT { 1.0f, 1.0f, 1.0f, 0 } - #define COLOR_BLACK_TRANSPARENT { 0, 0, 0, 0 } - #define COLOR_TRANSPARENT COLOR_BLACK_TRANSPARENT + #define COLOR_DEF(r,g,b,a) { r, g, b, a } + #define COLOR_WHITE COLOR_DEF(1.0f, 1.0f, 1.0f, 1.0f) + #define COLOR_RED COLOR_DEF(1.0f, 0, 0, 1.0f) + #define COLOR_GREEN COLOR_DEF(0, 1.0f, 0, 1.0f) + #define COLOR_BLUE COLOR_DEF(0, 0, 1.0f, 1.0f) + #define COLOR_BLACK COLOR_DEF(0, 0, 0, 1.0f) + #define COLOR_MAGENTA COLOR_DEF(1.0f, 0, 1.0f, 1.0f) + #define COLOR_DARK_GREY COLOR_DEF(0.2f, 0.2f, 0.2f, 1.0f) + #define COLOR_LIGHT_GREY COLOR_DEF(0.8f, 0.8f, 0.8f, 1.0f) + #define COLOR_CORNFLOWER_BLUE COLOR_DEF(0.4f, 0.6f, 0.9f, 1.0f) + #define COLOR_WHITE_TRANSPARENT COLOR_DEF(1.0f, 1.0f, 1.0f, 0.0f) + #define COLOR_BLACK_TRANSPARENT COLOR_DEF(0.0f, 0.0f, 0.0f, 0.0f) + #define COLOR_TRANSPARENT COLOR_BLACK_TRANSPARENT } \ No newline at end of file diff --git a/src/dawn/display/font/FontManager.cpp b/src/dawn/display/font/FontManager.cpp index f263139e..02b6b660 100644 --- a/src/dawn/display/font/FontManager.cpp +++ b/src/dawn/display/font/FontManager.cpp @@ -7,9 +7,18 @@ using namespace Dawn; +FontManager::FontManager() { + +} + void FontManager::init() { + // Init FreeType if(FT_Init_FreeType(&fontLibrary)) { std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl; assertUnreachable(); } +} + +FontManager::~FontManager() { + } \ No newline at end of file diff --git a/src/dawn/display/font/FontManager.hpp b/src/dawn/display/font/FontManager.hpp index 2d6221e2..0de6612f 100644 --- a/src/dawn/display/font/FontManager.hpp +++ b/src/dawn/display/font/FontManager.hpp @@ -14,6 +14,10 @@ namespace Dawn { public: FT_Library fontLibrary; + FontManager(); + void init(); + + ~FontManager(); }; } \ No newline at end of file diff --git a/src/dawn/display/font/NewTrueType.cpp b/src/dawn/display/font/NewTrueType.cpp index 50e2ea4b..7455c04d 100644 --- a/src/dawn/display/font/NewTrueType.cpp +++ b/src/dawn/display/font/NewTrueType.cpp @@ -7,17 +7,30 @@ using namespace Dawn; -void Dawn::_newTrueTypePlaceholder( - FT_Face face, - Texture &texture, - std::map &charStore +NewTrueTypeFaceTexture::NewTrueTypeFaceTexture( + NewTrueTypeFace *trueTypeFace, + FT_Face &face, + struct NewTrueTypeFaceTextureStyle style ) { + assertNotNull(trueTypeFace); + assertTrue(this->style.fontSize < 256); + + this->trueTypeFace = trueTypeFace; + this->face = &face; + this->style = style; + + // Set freetype font size prior to baking. + if(FT_Set_Pixel_Sizes(face, 0, this->style.fontSize)) { + assertUnreachable(); + } + size_t w = 0, h = 0; FT_ULong c; + // First pass, determine the textures' dimensions. for(c = NEW_TRUETYPE_CHAR_BEGIN; c < NEW_TRUETYPE_CHAR_END; c++) { // Load the character - if(FT_Load_Char(face, c, FT_LOAD_RENDER)) { + if(FT_Load_Char(face, c, FT_LOAD_RENDER | FT_LOAD_MONOCHROME)) { assertUnreachable(); } @@ -26,16 +39,18 @@ void Dawn::_newTrueTypePlaceholder( h += face->glyph->bitmap.rows; } + assertTrue(w > 0); + assertTrue(h > 0); // Now buffer pixels to the texture float_t y = 0; // I'd love to just buffer straight to the GPU, but it seems that is a bit // unstable right now. - uint8_t *buffer = (uint8_t *)memoryAllocate(w * h * sizeof(uint8_t)); - memorySet(buffer, 0x00, sizeof(uint8_t) * w * h); + uint8_t *buffer = (uint8_t *)memoryFillWithZero(w * h * sizeof(uint8_t)); size_t offset = 0; + struct NewTrueTypeCharacter info; for(c = NEW_TRUETYPE_CHAR_BEGIN; c < NEW_TRUETYPE_CHAR_END; c++) { // Load the character if(FT_Load_Char(face, c, FT_LOAD_RENDER)) { @@ -43,26 +58,51 @@ void Dawn::_newTrueTypePlaceholder( } // Store the character information - struct TrueTypeCharacterInfo info; - info.advance = glm::vec2(face->glyph->advance.x, face->glyph->advance.y); + info.advanceX = face->glyph->advance.x; + info.advanceY = face->glyph->advance.y; info.bitmapSize = glm::vec2(face->glyph->bitmap.width, face->glyph->bitmap.rows); - info.bitmapPosition = glm::vec2(face->glyph->bitmap_left, face->glyph->bitmap_top); + info.bitmapPosition = glm::vec2(face->glyph->bitmap_left, -face->glyph->bitmap_top); info.textureY = y; - charStore[c] = info; + this->characterData[c] = info; // Buffer the pixels, oh dear GOD there has to be a more efficient way. - for(uint32_t i = 0; i < face->glyph->bitmap.rows; i++) { + for(int32_t i = 0; i < face->glyph->bitmap.rows; i++) { memoryCopy( (void *)(face->glyph->bitmap.buffer + (i * face->glyph->bitmap.width)), (void *)(buffer + offset), face->glyph->bitmap.width * sizeof(uint8_t) ); offset += w * sizeof(uint8_t); + assertTrue(offset <= (w * h * sizeof(uint8_t))); } y += face->glyph->bitmap.rows; } - texture.setSize(w, h, TEXTURE_FORMAT_R); - texture.buffer(buffer); + this->texture.setSize(w, h, TEXTURE_FORMAT_R); + this->texture.buffer(buffer); memoryFree(buffer); +} + +struct NewTrueTypeCharacter NewTrueTypeFaceTexture::getCharacterData(FT_ULong c) { + return this->characterData[c]; +} + + + + +NewTrueTypeFace::NewTrueTypeFace(FT_Face *face) { + assertNotNull(face); + this->face = face; +} + +usagelockid_t NewTrueTypeFace::lock(struct NewTrueTypeFaceTextureStyle style) { + +} + +NewTrueTypeFace::~NewTrueTypeFace() { + auto it = this->textures.begin(); + while(it != this->textures.end()) { + delete *it; + it = this->textures.erase(it); + } } \ No newline at end of file diff --git a/src/dawn/display/font/NewTrueType.hpp b/src/dawn/display/font/NewTrueType.hpp index 3e8abc08..2c6f9644 100644 --- a/src/dawn/display/font/NewTrueType.hpp +++ b/src/dawn/display/font/NewTrueType.hpp @@ -6,22 +6,90 @@ #pragma once #include "dawnlibs.hpp" #include "util/mathutils.hpp" +#include "util/flag.hpp" #include "display/Texture.hpp" +#include "util/UsageLock.hpp" -#define NEW_TRUETYPE_CHAR_BEGIN 0x00 -#define NEW_TRUETYPE_CHAR_END 0xFF +#define NEW_TRUETYPE_CHAR_BEGIN 32 +#define NEW_TRUETYPE_CHAR_END 192 + +#define NEW_TRUETYPE_VARIANT_BOLD FLAG_DEFINE(0) +#define NEW_TRUETYPE_VARIANT_ITALICS FLAG_DEFINE(1) namespace Dawn { - struct TrueTypeCharacterInfo { - glm::vec2 advance; + class NewTrueTypeFace; + + typedef uint32_t newtruetypelock_t; + + struct NewTrueTypeCharacter { + int32_t advanceX; + int32_t advanceY; glm::vec2 bitmapSize; glm::vec2 bitmapPosition; float_t textureY; }; - void _newTrueTypePlaceholder( - FT_Face face, - Texture &texture, - std::map &charStore - ); + + struct NewTrueTypeFaceTextureStyle { + uint32_t fontSize; + flag_t style; + }; + + class NewTrueTypeFaceTexture { + protected: + FT_Face *face; + NewTrueTypeFace *trueTypeFace; + std::map characterData; + struct NewTrueTypeFaceTextureStyle style; + UsageLock locks; + + public: + Texture texture; + + /** + * Construct a new New True Type Face Texture object + * + * @param trueTypeFace Face that this texture belongs to. + * @param face The freetype face object. + * @param style Style that this font has, used for locking. + */ + NewTrueTypeFaceTexture( + NewTrueTypeFace *trueTypeFace, + FT_Face &face, + struct NewTrueTypeFaceTextureStyle style + ); + + /** + * Returns the character data for the given character. + * + * @param c Character to get data for. + * @return The Character data for the given character. + */ + struct NewTrueTypeCharacter getCharacterData(FT_ULong c); + + /** + * Destroys this true type face texture. + */ + ~NewTrueTypeFaceTexture(); + + friend class NewTrueTypeFace; + }; + + + + + class NewTrueTypeFace { + protected: + std::vector textures; + FT_Face *face; + std::map texturesByStyle; + std::map> locksByStyle; + + public: + NewTrueTypeFace(FT_Face *face); + usagelockid_t lock(struct NewTrueTypeFaceTextureStyle style); + void unlock(usagelockid_t lock); + NewTrueTypeFaceTexture * getTexture(usagelockid_t lock); + ~NewTrueTypeFace(); + }; } \ No newline at end of file diff --git a/src/dawn/scene/components/ui/UILabelNew.cpp b/src/dawn/scene/components/ui/UILabelNew.cpp index 4b4bb0c3..e0a80e87 100644 --- a/src/dawn/scene/components/ui/UILabelNew.cpp +++ b/src/dawn/scene/components/ui/UILabelNew.cpp @@ -8,7 +8,125 @@ using namespace Dawn; -void _uiLabelBake( +UILabelNew::UILabelNew(SceneItem *item) : UIComponentRenderable(item) { + +} + +void UILabelNew::onStart() { + this->shaderBuffer.init(); + + if(FT_New_Face( + getGame()->renderManager.getFontManager()->fontLibrary, + "/usr/share/fonts/TTF/arial.ttf", + // "C:\\Windows\\Fonts\\arial.ttf", + 0, + &face + )) { + assertUnreachable(); + } + UILabelNew::bakeTexture(defFace, face, 32); + + + if(FT_New_Face( + getGame()->renderManager.getFontManager()->fontLibrary, + "/usr/share/fonts/TTF/arialbd.ttf", + // "C:\\Windows\\Fonts\\arialbd.ttf", + 0, + &faceBold + )) { + assertUnreachable(); + } + UILabelNew::bakeTexture(defFaceBold, faceBold, 32); + + + if(FT_New_Face( + getGame()->renderManager.getFontManager()->fontLibrary, + "/usr/share/fonts/TTF/ariali.ttf", + // "C:\\Windows\\Fonts\\ariali.ttf", + 0, + &faceItalics + )) { + assertUnreachable(); + } + UILabelNew::bakeTexture(defFaceItalics, faceItalics, 32); + + struct FontShaderBufferData fontData; + glm::vec2 position = glm::vec2(32, 32); + + mesh.createBuffers(QUAD_VERTICE_COUNT * 128, QUAD_INDICE_COUNT * 128); + auto x = UILabelNew::bufferQuads( + "Hello ", + fontData, + defFace, + position, + 0, + 0 + ); + x += UILabelNew::bufferQuads( + " World", + fontData, + defFaceItalics, + position, + x, + 1 + ); + x += UILabelNew::bufferQuads( + " How are you?", + fontData, + defFaceBold, + position, + x, + 2 + ); + + fontData.colors[0] = COLOR_MAGENTA; + fontData.textures[0] = 0; + fontData.colors[1] = COLOR_RED; + fontData.textures[1] = 1; + fontData.colors[2] = COLOR_GREEN; + fontData.textures[2] = 2; + shaderBuffer.buffer(&fontData); +} + +std::vector UILabelNew::getUIRenderPasses() { + auto canvas = this->getCanvas(); + auto shader = getGame()->renderManager.fontShader; + + struct ShaderPassItem item; + item.shader = shader; + item.mesh = &this->mesh; + item.matrixValues[shader->paramModel] = transform->getWorldTransform(); + item.parameterBuffers[shader->bufferUiCanvas] = &canvas->shaderBuffer; + item.parameterBuffers[shader->bufferFont] = &this->shaderBuffer; + item.renderFlags = RENDER_MANAGER_RENDER_FLAG_BLEND; + item.textureSlots[0] = &defFace.texture; + item.textureSlots[1] = &defFaceItalics.texture; + item.textureSlots[2] = &defFaceBold.texture; + item.textureValues[shader->paramTexture0] = 0; + item.textureValues[shader->paramTexture1] = 1; + item.textureValues[shader->paramTexture2] = 2; + + return { item }; +} + + +float_t UILabelNew::getWidth() { + return 0; +} + +float_t UILabelNew::getHeight() { + return 0; +} + +float_t UILabelNew::getContentWidth() { + return 0; +} + +float_t UILabelNew::getContentHeight() { + return 0; +} + +void UILabelNew::bakeTexture( struct UILabelFontDef &fontDef, FT_Face &face, uint32_t fontSize @@ -78,155 +196,45 @@ void _uiLabelBake( memoryFree(buffer); } - - -int32_t _uiLabelQuad( +int32_t UILabelNew::bufferQuads( std::string text, - Mesh *mesh, struct FontShaderBufferData &bufferData, struct UILabelFontDef &fontDef, glm::vec2 &position, int32_t quadStart, int32_t partIndex ) { + // Get string length int32_t len = text.length(); - if(mesh == nullptr) return len; - - // Loop each char + glm::vec2 wh = glm::vec2(fontDef.texture.getWidth(), fontDef.texture.getHeight()); + // For each char for(int32_t i = 0; i < len; i++) { + char ch = text[i]; int32_t j = quadStart + i; - FT_ULong c = text[i]; + FT_ULong c = ch; auto &charInfo = fontDef.charStore[c]; + // Determine texture coordinates. glm::vec2 uv0 = glm::vec2(0.0f, charInfo.textureY) / wh; glm::vec2 uv1 = uv0 + (charInfo.bitmapSize / wh); - QuadMesh::bufferQuadMeshWithZ(mesh, + // Buffer the quad. + QuadMesh::bufferQuadMeshWithZ(&this->mesh, position + charInfo.bitmapPosition, uv0, position + charInfo.bitmapPosition + charInfo.bitmapSize, uv1, 0.0f, j * QUAD_VERTICE_COUNT, j * QUAD_INDICE_COUNT ); + // Move the current position along. position.x += (float_t)(charInfo.advanceX >> 6); position.y += (float_t)(charInfo.advanceY >> 6); - bufferData.fontQuadParts[j] = partIndex; + + // Set the part index to the quad mappings + bufferData.fontQuadMappings[j] = partIndex; } return len; -} - - - -UILabelNew::UILabelNew(SceneItem *item) : UIComponentRenderable(item) { - -} - -void UILabelNew::onStart() { - std::cout << "Hello new Label" << std::endl; - this->shaderBuffer.init(); - - - if(FT_New_Face( - getGame()->renderManager.getFontManager()->fontLibrary, - // "/usr/share/fonts/TTF/arial.ttf", - "C:\\Windows\\Fonts\\arial.ttf", - 0, - &face - )) { - assertUnreachable(); - } - _uiLabelBake(defFace, face, 32); - - - if(FT_New_Face( - getGame()->renderManager.getFontManager()->fontLibrary, - // "/usr/share/fonts/TTF/arialbd.ttf", - "C:\\Windows\\Fonts\\arialbd.ttf", - 0, - &faceBold - )) { - assertUnreachable(); - } - _uiLabelBake(defFaceBold, faceBold, 32); - - - if(FT_New_Face( - getGame()->renderManager.getFontManager()->fontLibrary, - // "/usr/share/fonts/TTF/ariali.ttf", - "C:\\Windows\\Fonts\\ariali.ttf", - 0, - &faceItalics - )) { - assertUnreachable(); - } - _uiLabelBake(defFaceItalics, faceItalics, 32); - - struct FontShaderBufferData fontData; - - glm::vec2 position = glm::vec2(32, 32); - - testMesh.createBuffers(QUAD_VERTICE_COUNT * 96, QUAD_INDICE_COUNT * 96); - auto x = _uiLabelQuad( - "Hello ", - &this->testMesh, - fontData, - defFace, - position, - 0, - 0 - ); - x += _uiLabelQuad( - "World", - &this->testMesh, - fontData, - defFaceItalics, - position, - x, - 1 - ); - - fontData.fontParts[0].color = COLOR_MAGENTA; - fontData.fontParts[0].texture = 0; - fontData.fontParts[1].color = COLOR_RED; - fontData.fontParts[1].texture = 1; - shaderBuffer.buffer(&fontData); -} - -std::vector UILabelNew::getUIRenderPasses() { - auto canvas = this->getCanvas(); - auto shader = getGame()->renderManager.fontShader; - - struct ShaderPassItem item; - item.shader = shader; - item.mesh = &testMesh; - item.matrixValues[shader->paramModel] = transform->getWorldTransform(); - item.parameterBuffers[shader->bufferUiCanvas] = &canvas->shaderBuffer; - item.parameterBuffers[shader->bufferFont] = &this->shaderBuffer; - item.renderFlags = RENDER_MANAGER_RENDER_FLAG_BLEND; - item.textureSlots[0] = &defFace.texture; - item.textureSlots[1] = &defFaceItalics.texture; - item.textureValues[shader->paramTexture0] = 0; - item.textureValues[shader->paramTexture1] = 1; - - return { item }; -} - - -float_t UILabelNew::getWidth() { - return 0; -} - -float_t UILabelNew::getHeight() { - return 0; -} - -float_t UILabelNew::getContentWidth() { - return 0; -} - -float_t UILabelNew::getContentHeight() { - return 0; } \ No newline at end of file diff --git a/src/dawn/scene/components/ui/UILabelNew.hpp b/src/dawn/scene/components/ui/UILabelNew.hpp index 946c75a9..d3bf3edd 100644 --- a/src/dawn/scene/components/ui/UILabelNew.hpp +++ b/src/dawn/scene/components/ui/UILabelNew.hpp @@ -7,38 +7,17 @@ #include "scene/components/ui/UIComponentRenderable.hpp" #include "display/mesh/QuadMesh.hpp" - -#define NEW_LABEL_CHAR_BEGIN 32 -#define NEW_LABEL_CHAR_END 192 - namespace Dawn { - struct UILabelChar { - int32_t advanceX; - int32_t advanceY; - glm::vec2 bitmapSize; - glm::vec2 bitmapPosition; - float_t textureY; - }; - - struct UILabelFontDef { - Texture texture; - uint32_t fontSize; - FT_Face *face; - std::map charStore; - }; - - struct UILabelPart { + struct UILabelStyle { + struct Color; UILabelFontDef *fontDef; - std::string text; }; class UILabelNew : public UIComponentRenderable { - protected: + private: Mesh mesh; FontShaderBuffer shaderBuffer; - Mesh testMesh; - FT_Face face; FT_Face faceBold; FT_Face faceItalics; @@ -47,6 +26,27 @@ namespace Dawn { struct UILabelFontDef defFaceBold; struct UILabelFontDef defFaceItalics; + /** + * Buffers the quads for the given text and updates the progressing values + * as the buffer process continues. + * + * @param text Text to buffer. + * @param bufferData The output quad mappings for the text. + * @param fontDef The font definition to use. + * @param position The 2D position to buffer the quads at. + * @param quadStart The starting quad index. + * @param partIndex The part index to store for each quad buffered. + * @return The number of quads buffered, not the string length. + */ + int32_t bufferQuads( + std::string text, + struct FontShaderBufferData &bufferData, + struct UILabelFontDef &fontDef, + glm::vec2 &position, + int32_t quadStart, + int32_t partIndex + ); + public: UILabelNew(SceneItem *item); diff --git a/src/dawnopengl/display/shader/shaders/FontShader.cpp b/src/dawnopengl/display/shader/shaders/FontShader.cpp index f7b9e75d..10148dc8 100644 --- a/src/dawnopengl/display/shader/shaders/FontShader.cpp +++ b/src/dawnopengl/display/shader/shaders/FontShader.cpp @@ -19,18 +19,18 @@ void FontShader::compile() { "#version 330 core\n" "layout (location = 0) in vec3 aPos;\n" "layout (location = 1) in vec2 aTexCoord;\n" + "layout (std140) uniform ub_UICanvas {\n" "mat4 u_View;\n" "mat4 u_Projection;\n" "};" - "struct FontShaderPart {\n" - "vec4 color;\n" - "int texture;\n" - "};\n" + "layout (shared) uniform ub_Font {\n" - "FontShaderPart u_FontParts[" MACRO_STRINGIFY(FONT_SHADER_PARTS_MAX) "];\n" - "int u_FontQuadParts[" MACRO_STRINGIFY(FONT_SHADER_QUADS_MAX) "];\n" + "int u_FontQuadMappings[" MACRO_STRINGIFY(FONT_SHADER_QUADS_MAX) "];\n" + "int u_FontTextures[" MACRO_STRINGIFY(FONT_SHADER_PARTS_MAX) "];\n" + "vec4 u_FontColors[" MACRO_STRINGIFY(FONT_SHADER_PARTS_MAX) "];\n" "};\n" + "uniform mat4 u_Model;\n" "out vec2 o_TextCoord;\n" "out vec4 o_VertColor;\n" @@ -40,10 +40,9 @@ void FontShader::compile() { "gl_Position = u_Projection * u_View * u_Model * vec4(aPos.xy, 0, 1.0);\n" "o_TextCoord = vec2(aTexCoord.x, aTexCoord.y);\n" "int quadIndex = gl_VertexID / " MACRO_STRINGIFY(QUAD_VERTICE_COUNT) ";\n" - "int partIndex = quadIndex < 5 ? 0 : 1;\n" - // "int partIndex = u_FontQuadParts[0];\n" - "o_VertColor = u_FontParts[partIndex].color;\n" - "o_TextIndex = u_FontParts[partIndex].texture;\n" + "int partIndex = u_FontQuadMappings[quadIndex];\n" + "o_VertColor = u_FontColors[partIndex];\n" + "o_TextIndex = u_FontTextures[partIndex];\n" "}", // Fragment Shader @@ -54,16 +53,19 @@ void FontShader::compile() { "out vec4 o_Color;\n" "uniform sampler2D u_Text0;\n" "uniform sampler2D u_Text1;\n" + "uniform sampler2D u_Text2;\n" "void main() {\n" "o_Color = o_VertColor;\n" - "vec4 textColor;\n" + "vec4 tColor;" "if(o_TextIndex == 0) \n{" - "textColor = texture(u_Text0, o_TextCoord);\n" + "tColor = texture(u_Text0, o_TextCoord);\n" + "} else if(o_TextIndex == 1) \n{" + "tColor = texture(u_Text1, o_TextCoord);\n" "} else {\n" - "textColor = texture(u_Text1, o_TextCoord);\n" + "tColor = texture(u_Text2, o_TextCoord);\n" "}\n" - "o_Color.a = textColor.r;\n" + "o_Color.a *= tColor.r;\n" "}\n" ); #else @@ -75,4 +77,5 @@ void FontShader::compile() { this->bufferFont = this->getBufferLocationByName("ub_Font"); this->paramTexture0 = this->getParameterByName("u_Text0"); this->paramTexture1 = this->getParameterByName("u_Text1"); + this->paramTexture2 = this->getParameterByName("u_Text2"); } \ No newline at end of file diff --git a/src/dawnopengl/display/shader/shaders/FontShader.hpp b/src/dawnopengl/display/shader/shaders/FontShader.hpp index 1e5fc53b..80628b05 100644 --- a/src/dawnopengl/display/shader/shaders/FontShader.hpp +++ b/src/dawnopengl/display/shader/shaders/FontShader.hpp @@ -7,24 +7,18 @@ #include "UIShader.hpp" #include "util/macro.hpp" -#define FONT_SHADER_PARTS_MAX 6 -#define FONT_SHADER_QUADS_MAX 64 +#define FONT_SHADER_PARTS_MAX 4 +#define FONT_SHADER_QUADS_MAX 32 #define FONT_SHADER_TEXTURE_MAX 8 namespace Dawn { - #pragma pack(push, 1) - struct FontShaderPart { - struct Color color; - int32_t texture; - }; - #pragma pack(pop) - - #pragma pack(push, 1) + // #pragma pack(push, 4) struct FontShaderBufferData { - struct FontShaderPart fontParts[FONT_SHADER_PARTS_MAX]; - int32_t fontQuadParts[FONT_SHADER_QUADS_MAX]; + int32_t fontQuadMappings[FONT_SHADER_QUADS_MAX]; + int32_t textures[FONT_SHADER_PARTS_MAX]; + struct Color colors[FONT_SHADER_PARTS_MAX]; }; - #pragma pack(pop) + // #pragma pack(pop) class FontShaderBuffer : public ShaderParameterBuffer { @@ -35,6 +29,7 @@ namespace Dawn { shaderparameter_t paramModel; shaderparameter_t paramTexture0; shaderparameter_t paramTexture1; + shaderparameter_t paramTexture2; shaderbufferlocation_t bufferUiCanvas; shaderbufferlocation_t bufferFont; diff --git a/src/dawnshared/CMakeLists.txt b/src/dawnshared/CMakeLists.txt index e2caf75f..dfc3c7de 100644 --- a/src/dawnshared/CMakeLists.txt +++ b/src/dawnshared/CMakeLists.txt @@ -18,6 +18,7 @@ set( DAWN_SHARED_SOURCES ${D}/assert/assert.cpp ${D}/util/Xml.cpp + ${D}/util/UsageLock.cpp CACHE INTERNAL ${DAWN_CACHE_TARGET} diff --git a/src/dawnshared/util/UsageLock.cpp b/src/dawnshared/util/UsageLock.cpp new file mode 100644 index 00000000..d54154ac --- /dev/null +++ b/src/dawnshared/util/UsageLock.cpp @@ -0,0 +1,27 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "util/UsageLock.hpp" + +using namespace Dawn; + +UsageLock::UsageLock() { + this->onEmpty = []() {}; + this->onFirstLock = []() {}; +} + +usagelockid_t UsageLock::createLock() { + usagelockid_t lock = this->nextLock++; + this->locks.push_back(lock); + if(this->locks.size() == 1) this->onFirstLock(); + return lock; +} + +void UsageLock::removeLock(usagelockid_t lock) { + auto it = std::find(this->locks.begin(), this->locks.end(), lock); + if(it == this->locks.end()) return; + this->locks.erase(it); + if(this->locks.size() == 0) this->onEmpty(); +} \ No newline at end of file diff --git a/src/dawnshared/util/UsageLock.hpp b/src/dawnshared/util/UsageLock.hpp new file mode 100644 index 00000000..18ecbfa6 --- /dev/null +++ b/src/dawnshared/util/UsageLock.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "assert/assert.hpp" + +namespace Dawn { + typedef uint32_t usagelockid_t; + + class UsageLock { + protected: + usagelockid_t nextLock = 0; + std::vector locks; + + public: + std::function onEmpty; + std::function onFirstLock; + + /** + * Construct a new usage lock object. + */ + UsageLock(); + + /** + * Creates a new lock. + * + * @return Lock created for this specific instance. + */ + usagelockid_t createLock(); + + /** + * Removes a lock. + * + * @param lock Lck to remove. + */ + void removeLock(usagelockid_t lock); + }; +} \ No newline at end of file