From 0224ec3af3ccef29c47ee1d044e72fe56f9e5255 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Wed, 13 Dec 2023 22:55:13 -0600 Subject: [PATCH] Finished UI Render Context --- src/dawn/component/ui/UICanvas.cpp | 85 ++++++++++++++----- src/dawn/component/ui/UICanvas.hpp | 28 +++++- src/dawn/ui/UIComponent.cpp | 9 +- src/dawn/ui/UIComponent.hpp | 11 +-- src/dawn/ui/UILabel.cpp | 19 ++--- src/dawn/ui/UILabel.hpp | 2 +- src/dawn/ui/UIRectangle.cpp | 10 +-- src/dawn/ui/UIRectangle.hpp | 2 +- src/dawnhelloworld/scene/HelloWorldScene.cpp | 8 +- src/dawnopengl/display/shader/ShaderStage.cpp | 2 +- src/dawnopengl/display/shader/UIShader.cpp | 52 ++++++++++-- src/dawnopengl/display/shader/UIShader.hpp | 3 + 12 files changed, 163 insertions(+), 68 deletions(-) diff --git a/src/dawn/component/ui/UICanvas.cpp b/src/dawn/component/ui/UICanvas.cpp index dbc4b18f..917b7564 100644 --- a/src/dawn/component/ui/UICanvas.cpp +++ b/src/dawn/component/ui/UICanvas.cpp @@ -5,9 +5,8 @@ #include "UICanvas.hpp" #include "display/pass/RenderPass.hpp" -#include "display/shader/UIShader.hpp" - #include "display/mesh/QuadMesh.hpp" +#include "ui/UIComponent.hpp" using namespace Dawn; @@ -35,32 +34,70 @@ void UICanvas::onDispose() { } std::vector> UICanvas::getPasses( - struct RenderPassContext &ctx +struct RenderPassContext &ctx ) { - std::vector> passes; - std::unordered_map> textures; - UIShaderData data = { - .projection = ctx.camera->getProjection(), - .view = ctx.camera->getItem()->getWorldTransform(), - .model = this->getItem()->getWorldTransform() - }; - - size_t quadCount = 0; + if(this->components.empty()) return {}; + + data.projection = ctx.camera->getProjection(); + data.view = ctx.camera->getItem()->getWorldTransform(); + data.model = this->getItem()->getWorldTransform(); + + this->passes.clear(); + this->textureBindings.clear(); + this->textures.clear(); + quadCount = 0; + nextBinding = 0; + auto itComponents = components.begin(); + auto self = std::ref(*this); while(itComponents != components.end()) { auto component = *itComponents; - - // Get this components' quads. - auto quads = component->getQuads({ 0, 0 }); - for(auto quad : quads) { - data.quads[quadCount++] = quad; - assertTrue(quadCount <= UI_SHADER_QUAD_COUNT, "Too many UI quads!"); - } + component->getQuads({ 0, 0 }, self); ++itComponents; } + flushPass(); - // No render passes if no quads. - if(quadCount == 0) return passes; + return passes; +} + +void UICanvas::addQuad( + const glm::vec4 quad, + const glm::vec4 uvs, + const struct Color color, + const std::shared_ptr text +) { + float_t fTexture = -1; + if(text == nullptr) { + fTexture = -1; + } else { + shadertexturebinding_t texture; + auto bindingIt = textureBindings.find(text); + if(bindingIt == textureBindings.end()) { + if(nextBinding >= UI_SHADER_TEXTURE_COUNT) { + flushPass(); + } + textureBindings[text] = nextBinding; + textures[nextBinding] = text; + data.textures[nextBinding] = nextBinding; + texture = nextBinding++; + } else { + texture = bindingIt->second; + } + fTexture = (float_t)texture; + } + + data.quads[quadCount] = { + quad, + uvs, + color, + fTexture + }; + quadCount++; + if(quadCount == UI_SHADER_QUAD_COUNT) flushPass(); +} + +void UICanvas::flushPass() { + if(quadCount == 0) return; auto pass = createRenderPass( std::ref(*this), @@ -73,6 +110,8 @@ std::vector> UICanvas::getPasses( ); passes.push_back(pass); - - return passes; + quadCount = 0; + nextBinding = 0; + textures.clear(); + textureBindings.clear(); } \ No newline at end of file diff --git a/src/dawn/component/ui/UICanvas.hpp b/src/dawn/component/ui/UICanvas.hpp index 4c121715..124610cd 100644 --- a/src/dawn/component/ui/UICanvas.hpp +++ b/src/dawn/component/ui/UICanvas.hpp @@ -6,25 +6,47 @@ #pragma once #include "scene/SceneItem.hpp" #include "component/display/IRenderableComponent.hpp" -#include "ui/UIComponent.hpp" +#include "display/shader/UIShader.hpp" namespace Dawn { + class UIComponent; + class UICanvas : public SceneComponent, public IRenderableComponent { - protected: + private: std::shared_ptr mesh; + UIShaderData data; + size_t quadCount = 0; + shadertexturebinding_t nextBinding = 0; + std::unordered_map< + shadertexturebinding_t, std::shared_ptr + > textures; + std::map< + std::shared_ptr, shadertexturebinding_t + > textureBindings; + + std::vector> passes; + + protected: virtual void onInit() override; virtual void onDispose() override; + void flushPass(); public: std::vector> components; - std::vector> getPasses( struct RenderPassContext &ctx ) override; + + void addQuad( + const glm::vec4 quad, + const glm::vec4 uvs, + const struct Color color, + const std::shared_ptr texture + ); }; } \ No newline at end of file diff --git a/src/dawn/ui/UIComponent.cpp b/src/dawn/ui/UIComponent.cpp index c7e377ee..276462e2 100644 --- a/src/dawn/ui/UIComponent.cpp +++ b/src/dawn/ui/UIComponent.cpp @@ -11,15 +11,12 @@ std::vector> UIComponent::getChildren() { return {}; } -std::vector UIComponent::getQuads(const glm::vec2 parent) { +void UIComponent::getQuads(const glm::vec2 parent, UICanvas &ctx) { glm::vec2 transform = parent + position; - std::vector quads = this->getSelfQuads(transform); + this->getSelfQuads(transform, ctx); auto children = getChildren(); for(auto &c : children) { - auto childQuads = c->getQuads(transform); - quads.insert(quads.end(), childQuads.begin(), childQuads.end()); + c->getQuads(transform, ctx); } - - return quads; } \ No newline at end of file diff --git a/src/dawn/ui/UIComponent.hpp b/src/dawn/ui/UIComponent.hpp index b8ec683d..90158cb2 100644 --- a/src/dawn/ui/UIComponent.hpp +++ b/src/dawn/ui/UIComponent.hpp @@ -6,19 +6,14 @@ #pragma once #include "ui/UIAlign.hpp" #include "display/shader/UIShader.hpp" +#include "component/ui/UICanvas.hpp" namespace Dawn { - class UICanvas; - class UIComponent { protected: - virtual std::vector getSelfQuads( - const glm::vec2 t - ) = 0; - + virtual void getSelfQuads(const glm::vec2 t, UICanvas &ctx) = 0; virtual std::vector> getChildren(); - - std::vector getQuads(const glm::vec2 parent); + void getQuads(const glm::vec2 parent, UICanvas &ctx); public: glm::vec2 position; diff --git a/src/dawn/ui/UILabel.cpp b/src/dawn/ui/UILabel.cpp index ac44532a..dc079ca7 100644 --- a/src/dawn/ui/UILabel.cpp +++ b/src/dawn/ui/UILabel.cpp @@ -7,30 +7,29 @@ using namespace Dawn; -std::vector UILabel::getSelfQuads(const glm::vec2 t) { +void UILabel::getSelfQuads(const glm::vec2 t, UICanvas &ctx) { std::vector quads; - if(this->texture == nullptr) return quads; + if(this->texture == nullptr) return; - const std::wstring text = L"Hello World!"; + const std::wstring text = L"He"; glm::vec2 position = t; glm::vec4 quad; for(wchar_t c : text) { auto info = texture->getCharacterData(c); - quads.push_back({ - .quad = { + ctx.addQuad( + { position.x, position.y, position.x + info.size.x, position.y + info.size.y }, - .uv = info.quad, - .color = COLOR_WHITE - }); + info.quad, + COLOR_WHITE, + texture->texture + ); position += info.advance; } - - return quads; } void UILabel::setFont(std::shared_ptr texture) { diff --git a/src/dawn/ui/UILabel.hpp b/src/dawn/ui/UILabel.hpp index 4faac414..6533a82c 100644 --- a/src/dawn/ui/UILabel.hpp +++ b/src/dawn/ui/UILabel.hpp @@ -13,7 +13,7 @@ namespace Dawn { std::shared_ptr texture = nullptr; protected: - std::vector getSelfQuads(const glm::vec2 t) override; + void getSelfQuads(const glm::vec2 t, UICanvas &ctx) override; public: void setFont(std::shared_ptr texture); diff --git a/src/dawn/ui/UIRectangle.cpp b/src/dawn/ui/UIRectangle.cpp index c27399fa..7cadac8a 100644 --- a/src/dawn/ui/UIRectangle.cpp +++ b/src/dawn/ui/UIRectangle.cpp @@ -7,12 +7,12 @@ using namespace Dawn; -std::vector UIRectangle::getSelfQuads(const glm::vec2 t) { +void UIRectangle::getSelfQuads(const glm::vec2 t, UICanvas &ctx) { std::vector quads; - quads.push_back({ + ctx.addQuad( glm::vec4(t, t + size), uv, - color - }); - return quads; + color, + nullptr + ); } \ No newline at end of file diff --git a/src/dawn/ui/UIRectangle.hpp b/src/dawn/ui/UIRectangle.hpp index f98ccf2d..4f9d592d 100644 --- a/src/dawn/ui/UIRectangle.hpp +++ b/src/dawn/ui/UIRectangle.hpp @@ -9,7 +9,7 @@ namespace Dawn { class UIRectangle final : public UIComponent { protected: - std::vector getSelfQuads(const glm::vec2 t) override; + void getSelfQuads(const glm::vec2 t, UICanvas &ctx) override; public: struct Color color = COLOR_WHITE; diff --git a/src/dawnhelloworld/scene/HelloWorldScene.cpp b/src/dawnhelloworld/scene/HelloWorldScene.cpp index e3b65a84..255f6758 100644 --- a/src/dawnhelloworld/scene/HelloWorldScene.cpp +++ b/src/dawnhelloworld/scene/HelloWorldScene.cpp @@ -52,10 +52,10 @@ void Dawn::helloWorldScene(Scene &s) { auto uiCanvasItem = s.createSceneItem(); auto uiCanvas = uiCanvasItem->addComponent(); - auto rect = std::make_shared(); - rect->position = { -32, -32 }; - rect->color = COLOR_MAGENTA; - uiCanvas->components.push_back(rect); + // auto rect = std::make_shared(); + // rect->position = { -32, -32 }; + // rect->color = COLOR_MAGENTA; + // uiCanvas->components.push_back(rect); auto label = std::make_shared(); label->setFont(texture); diff --git a/src/dawnopengl/display/shader/ShaderStage.cpp b/src/dawnopengl/display/shader/ShaderStage.cpp index 8ea49c15..e48c5a16 100644 --- a/src/dawnopengl/display/shader/ShaderStage.cpp +++ b/src/dawnopengl/display/shader/ShaderStage.cpp @@ -57,7 +57,7 @@ ShaderStage::ShaderStage( GLchar *log = new GLchar[logLength]; glGetShaderInfoLog(this->id, logLength, NULL, log); assertNoGLError(); - assertUnreachable("Failed to compile shader stage:\n%s", log); + assertUnreachable("Failed to compile shader stage %i:\n%s", type, log); } } diff --git a/src/dawnopengl/display/shader/UIShader.cpp b/src/dawnopengl/display/shader/UIShader.cpp index ba8f9052..600a3c06 100644 --- a/src/dawnopengl/display/shader/UIShader.cpp +++ b/src/dawnopengl/display/shader/UIShader.cpp @@ -33,19 +33,21 @@ void UIShader::getStages( "vec4 quad;\n" "vec4 uv;\n" "vec4 color;\n" + "float texture;\n" "};\n" "layout (std140) uniform ub_Quad {\n" "UIShaderQuad quads[" MACRO_STRINGIFY(UI_SHADER_QUAD_COUNT) "];\n" "};\n" - "out vec2 o_TextCoord;\n" + "out vec2 v_TextCoord;\n" "out vec4 v_Color;\n" + "out float v_TextureIndex;\n" "void main() {\n" "vec4 pos;\n" "vec2 coord;\n" "int index = int(aPos.z);\n" "int quadIndex = index / 4;\n" "int vertexIndex = index % 4;\n" - "struct UIShaderQuad quad = quads[quadIndex];\n" + "UIShaderQuad quad = quads[quadIndex];\n" "if(vertexIndex == 0) {\n" "pos.x = quad.quad.x;\n" "pos.y = quad.quad.y;\n" @@ -70,19 +72,44 @@ void UIShader::getStages( "pos.z = 0;\n" "pos.w = 1;\n" "gl_Position = u_Projection * u_View * u_Model * pos;\n" - "o_TextCoord = coord;\n" + "v_TextCoord = coord;\n" "v_Color = quad.color;\n" + "v_TextureIndex = quad.texture;\n" "}" ); fragment = std::make_shared( ShaderStageType::FRAGMENT, "#version 330 core\n" - "in vec2 o_TextCoord;\n" + "in vec2 v_TextCoord;\n" "in vec4 v_Color;\n" - "out vec4 o_Color;\n" + "in float v_TextureIndex;\n" + "uniform sampler2D u_Texture[" MACRO_STRINGIFY(UI_SHADER_TEXTURE_COUNT) "];\n" + "out vec4 o_Color;\n" "void main() {\n" - "o_Color = v_Color;\n" + "vec4 texColor = vec4(1, 1, 1, 1);\n" + // "switch(int(v_TextureIndex)) {\n" + // "case 0:\n" + // "texColor = texture(u_Texture[0], v_TextCoord);\n" + // "break;\n" + // "case 1:\n" + // "texColor = texture(u_Texture[1], v_TextCoord);\n" + // "break;\n" + // "case 2:\n" + // "texColor = texture(u_Texture[2], v_TextCoord);\n" + // "break;\n" + // "case 3:\n" + // "texColor = texture(u_Texture[3], v_TextCoord);\n" + // "break;\n" + // "case 4:\n" + // "texColor = texture(u_Texture[4], v_TextCoord);\n" + // "break;\n" + // "case 5:\n" + // "texColor = texture(u_Texture[5], v_TextCoord);\n" + // "break;\n" + // "}\n" + "texColor = texture(u_Texture[0], v_TextCoord);\n" + "o_Color = texColor * v_Color;\n" "}\n" ); break; @@ -113,6 +140,13 @@ void UIShader::getStages( &rel->model, ShaderParameterType::MAT4 )); + + parameters.push_back(ShaderParameter( + "u_Texture", + &rel->textures, + ShaderParameterType::TEXTURE, + UI_SHADER_TEXTURE_COUNT + )); structures.push_back(ShaderStructure( "ub_Quad", @@ -136,6 +170,12 @@ void UIShader::getStages( &rel.color, ShaderParameterType::COLOR )); + + parameters.push_back(ShaderParameter( + "u_Texture", + &rel.texture, + ShaderParameterType::TEXTURE + )); }, UI_SHADER_QUAD_COUNT )); diff --git a/src/dawnopengl/display/shader/UIShader.hpp b/src/dawnopengl/display/shader/UIShader.hpp index 0fdf7aa8..f5013748 100644 --- a/src/dawnopengl/display/shader/UIShader.hpp +++ b/src/dawnopengl/display/shader/UIShader.hpp @@ -8,17 +8,20 @@ namespace Dawn { #define UI_SHADER_QUAD_COUNT 32 + #define UI_SHADER_TEXTURE_COUNT 6 struct UIShaderQuad { glm::vec4 quad; glm::vec4 uv; struct Color color; + float_t texture; }; struct UIShaderData { glm::mat4 projection; glm::mat4 view; glm::mat4 model; + shadertexturebinding_t textures[UI_SHADER_TEXTURE_COUNT]; struct UIShaderQuad quads[UI_SHADER_QUAD_COUNT]; };