diff --git a/src/dawn/component/ui/UICanvas.cpp b/src/dawn/component/ui/UICanvas.cpp index 5dc6fe11..c6f18cf3 100644 --- a/src/dawn/component/ui/UICanvas.cpp +++ b/src/dawn/component/ui/UICanvas.cpp @@ -12,52 +12,66 @@ using namespace Dawn; void UICanvas::onInit() { - + mesh = std::make_shared(); + mesh->createBuffers( + QUAD_VERTICE_COUNT * UI_SHADER_QUAD_COUNT, + QUAD_INDICE_COUNT * UI_SHADER_QUAD_COUNT + ); + + for(int32_t i = 0; i < UI_SHADER_QUAD_COUNT; i++) { + QuadMesh::bufferWithIndex( + mesh, + glm::vec4(0, 0, 1, 1), + glm::vec4(0, 0, 1, 1), + i * QUAD_VERTICE_COUNT, + i * QUAD_INDICE_COUNT, + i * QUAD_VERTICE_COUNT + ); + } } void UICanvas::onDispose() { - + mesh = nullptr; } std::vector> UICanvas::getPasses( struct RenderPassContext &ctx ) { std::vector> passes; - - auto selfTransform = this->getItem()->getWorldTransform(); - - auto mesh = std::make_shared(); - mesh->createBuffers(QUAD_VERTICE_COUNT, QUAD_INDICE_COUNT); - QuadMesh::buffer(mesh, glm::vec4(0, 0, 32, 32), glm::vec4(0, 0, 1, 1), 0, 0); + std::unordered_map> textures; UIShaderData data = { .projection = ctx.camera->getProjection(), .view = ctx.camera->getItem()->getWorldTransform(), - .model = selfTransform + .model = this->getItem()->getWorldTransform() }; - data.test.first = COLOR_RED; - data.test.random = glm::vec3(0, 1, 0); - data.test.second = COLOR_BLUE; - - auto pass = createRenderPass( - std::ref(*this), - data, - std::unordered_map>(), - mesh, - MeshDrawMode::TRIANGLES, - 0, -1 - ); - passes.push_back(pass); - + size_t quadCount = 0; auto itComponents = components.begin(); while(itComponents != components.end()) { auto component = *itComponents; // Get this components' quads. - auto quads = component->getQuads(selfTransform); - + auto quads = component->getQuads(glm::mat4(1.0)); + for(auto quad : quads) { + data.quads[quadCount++] = quad; + assertTrue(quadCount <= UI_SHADER_QUAD_COUNT, "Too many UI quads!"); + } ++itComponents; } + // No render passes if no quads. + if(quadCount == 0) return passes; + + auto pass = createRenderPass( + std::ref(*this), + data, + textures, + mesh, + MeshDrawMode::TRIANGLES, + 0, quadCount * QUAD_INDICE_COUNT + ); + passes.push_back(pass); + + return passes; } \ No newline at end of file diff --git a/src/dawn/component/ui/UICanvas.hpp b/src/dawn/component/ui/UICanvas.hpp index 1e75fa69..4c121715 100644 --- a/src/dawn/component/ui/UICanvas.hpp +++ b/src/dawn/component/ui/UICanvas.hpp @@ -14,6 +14,8 @@ namespace Dawn { public IRenderableComponent { protected: + std::shared_ptr mesh; + virtual void onInit() override; virtual void onDispose() override; diff --git a/src/dawn/display/mesh/QuadMesh.cpp b/src/dawn/display/mesh/QuadMesh.cpp index 8fb6e0d4..c094c2e6 100644 --- a/src/dawn/display/mesh/QuadMesh.cpp +++ b/src/dawn/display/mesh/QuadMesh.cpp @@ -12,13 +12,46 @@ void QuadMesh::buffer( const glm::vec4 positions, const glm::vec4 coordinates, const int32_t verticeStart, - const int32_t indiceStart + const int32_t indiceStart, + const float_t depth ) { glm::vec3 vertices[QUAD_VERTICE_COUNT] = { - glm::vec3(positions.x, positions.y, 0), - glm::vec3(positions.z, positions.y, 0), - glm::vec3(positions.x, positions.w, 0), - glm::vec3(positions.z, positions.w, 0) + glm::vec3(positions.x, positions.y, depth), + glm::vec3(positions.z, positions.y, depth), + glm::vec3(positions.x, positions.w, depth), + glm::vec3(positions.z, positions.w, depth) + }; + + glm::vec2 coords[QUAD_VERTICE_COUNT] = { + glm::vec2(coordinates.x, coordinates.y), + glm::vec2(coordinates.z, coordinates.y), + glm::vec2(coordinates.x, coordinates.w), + glm::vec2(coordinates.z, coordinates.w) + }; + + int32_t indices[QUAD_INDICE_COUNT] = { + verticeStart, verticeStart + 1, verticeStart + 3, + verticeStart, verticeStart + 2, verticeStart + 3 + }; + + mesh->bufferPositions(verticeStart, vertices, QUAD_VERTICE_COUNT); + mesh->bufferCoordinates(verticeStart, coords, QUAD_VERTICE_COUNT); + mesh->bufferIndices(indiceStart, indices, QUAD_INDICE_COUNT); +} + +void QuadMesh::bufferWithIndex( + const std::shared_ptr mesh, + const glm::vec4 positions, + const glm::vec4 coordinates, + const int32_t verticeStart, + const int32_t indiceStart, + const int32_t indexOffset +) { + glm::vec3 vertices[QUAD_VERTICE_COUNT] = { + glm::vec3(positions.x, positions.y, indexOffset), + glm::vec3(positions.z, positions.y, indexOffset + 1), + glm::vec3(positions.x, positions.w, indexOffset + 2), + glm::vec3(positions.z, positions.w, indexOffset + 3) }; glm::vec2 coords[QUAD_VERTICE_COUNT] = { diff --git a/src/dawn/display/mesh/QuadMesh.hpp b/src/dawn/display/mesh/QuadMesh.hpp index bbe15ecb..009fcdad 100644 --- a/src/dawn/display/mesh/QuadMesh.hpp +++ b/src/dawn/display/mesh/QuadMesh.hpp @@ -20,13 +20,36 @@ namespace Dawn { * @param coordinates The coordinates of the vertices. * @param verticeStart The starting index of the vertices. * @param indiceStart The starting index of the indices. + * @param depth The depth of the vertices (Z coordinate). */ static void buffer( const std::shared_ptr mesh, const glm::vec4 positions, const glm::vec4 coordinates, const int32_t verticeStart, - const int32_t indiceStart + const int32_t indiceStart, + const float_t depth = 0.0f + ); + + /** + * Buffers quad mesh vertices and indices into the given mesh. This will + * store the index of the vertice in the Z component, allowing you to find + * which vertex ID you are rendering in your shader. + * + * @param mesh The mesh to buffer into. + * @param positions The positions of the vertices. + * @param coordinates The coordinates of the vertices. + * @param verticeStart The starting index of the vertices. + * @param indiceStart The starting index of the indices. + * @param indexOffset The offset to add to the index of each vertex. + */ + static void bufferWithIndex( + const std::shared_ptr mesh, + const glm::vec4 positions, + const glm::vec4 coordinates, + const int32_t verticeStart, + const int32_t indiceStart, + const int32_t indexOffset = 0 ); }; } \ No newline at end of file diff --git a/src/dawn/ui/UIComponent.cpp b/src/dawn/ui/UIComponent.cpp index 9e3fc14d..2469e7cb 100644 --- a/src/dawn/ui/UIComponent.cpp +++ b/src/dawn/ui/UIComponent.cpp @@ -11,20 +11,20 @@ std::vector> UIComponent::getChildren() { return {}; } -std::vector UIComponent::getQuads( +std::vector UIComponent::getQuads( const glm::mat4 parent ) { // Get self transform glm::mat4 transform = glm::translate( - glm::mat4(1.0f), glm::vec3(position, 0.0f) + glm::mat4(1.0f), + glm::vec3(position, 0.0f) ); // Add parent transform transform = parent * transform; // Get self quads and insert new transform. - std::vector quads; - auto selfQuads = this->getSelfQuads(transform); + std::vector quads = this->getSelfQuads(transform); // Get children auto children = getChildren(); diff --git a/src/dawn/ui/UIComponent.hpp b/src/dawn/ui/UIComponent.hpp index c4b86877..66a43de3 100644 --- a/src/dawn/ui/UIComponent.hpp +++ b/src/dawn/ui/UIComponent.hpp @@ -5,20 +5,20 @@ #pragma once #include "ui/UIAlign.hpp" -#include "ui/UIQuad.hpp" +#include "display/shader/UIShader.hpp" namespace Dawn { class UICanvas; class UIComponent { protected: - virtual std::vector getSelfQuads( + virtual std::vector getSelfQuads( const glm::mat4 transform ) = 0; virtual std::vector> getChildren(); - std::vector getQuads( + std::vector getQuads( const glm::mat4 parent ); diff --git a/src/dawn/ui/UIQuad.hpp b/src/dawn/ui/UIQuad.hpp deleted file mode 100644 index 5b727609..00000000 --- a/src/dawn/ui/UIQuad.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2023 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -#pragma once -#include "display/Color.hpp" -#include "display/Texture.hpp" - -namespace Dawn { - struct UIQuad { - glm::mat4 transform; - glm::vec4 quad; - glm::vec4 uv; - struct Color color; - std::shared_ptr texture; - - UIQuad( - const glm::mat4 transform, - const glm::vec4 quad, - const glm::vec4 uv, - const struct Color color, - const std::shared_ptr texture - ) : - transform(transform), - quad(quad), - uv(uv), - color(color), - texture(texture) - { - - } - }; -} \ No newline at end of file diff --git a/src/dawn/ui/UIRectangle.cpp b/src/dawn/ui/UIRectangle.cpp index b4fa3e8b..9c25786d 100644 --- a/src/dawn/ui/UIRectangle.cpp +++ b/src/dawn/ui/UIRectangle.cpp @@ -7,18 +7,15 @@ using namespace Dawn; -std::vector UIRectangle::getSelfQuads( +std::vector UIRectangle::getSelfQuads( const glm::mat4 transform ) { - std::vector quads; - - quads.push_back(UIQuad( + std::vector quads; + quads.push_back({ transform, - glm::vec4(0,0,size.x,size.y), + glm::vec4(0, 0, size.x, size.y), uv, - color, - texture - )); - + color + }); return quads; } \ No newline at end of file diff --git a/src/dawn/ui/UIRectangle.hpp b/src/dawn/ui/UIRectangle.hpp index 826bba31..3f6dbe21 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( + std::vector getSelfQuads( const glm::mat4 transform ) override; diff --git a/src/dawn/util/Macro.hpp b/src/dawn/util/Macro.hpp new file mode 100644 index 00000000..bcfb26e8 --- /dev/null +++ b/src/dawn/util/Macro.hpp @@ -0,0 +1,11 @@ +// Copyright (c) 2023 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once + +#define MACRO_STRINGIFY_RAW(x) #x +#define MACRO_STRINGIFY(x) MACRO_STRINGIFY_RAW(x) + +#define MACRO_JOIN(x, y) x ## y \ No newline at end of file diff --git a/src/dawnhelloworld/scene/HelloWorldScene.cpp b/src/dawnhelloworld/scene/HelloWorldScene.cpp index 87553782..fa0ac942 100644 --- a/src/dawnhelloworld/scene/HelloWorldScene.cpp +++ b/src/dawnhelloworld/scene/HelloWorldScene.cpp @@ -53,5 +53,11 @@ void Dawn::helloWorldScene(Scene &s) { auto uiCanvas = uiCanvasItem->addComponent(); auto rect = std::make_shared(); + rect->position = { -32, -32 }; uiCanvas->components.push_back(rect); + + auto rect2 = std::make_shared(); + rect2->color = COLOR_MAGENTA; + rect2->position = { 10, 10 }; + uiCanvas->components.push_back(rect2); } \ No newline at end of file diff --git a/src/dawnopengl/display/shader/Shader.hpp b/src/dawnopengl/display/shader/Shader.hpp index 28378a26..86109020 100644 --- a/src/dawnopengl/display/shader/Shader.hpp +++ b/src/dawnopengl/display/shader/Shader.hpp @@ -208,7 +208,7 @@ namespace Dawn { assertNoGLError(); glBufferData( GL_UNIFORM_BUFFER, - structure.size, + structure.size * structure.count, (void*)((size_t)&this->data + (size_t)structure.offset), GL_STATIC_DRAW ); diff --git a/src/dawnopengl/display/shader/ShaderStructure.hpp b/src/dawnopengl/display/shader/ShaderStructure.hpp index 4cbc9048..dc672560 100644 --- a/src/dawnopengl/display/shader/ShaderStructure.hpp +++ b/src/dawnopengl/display/shader/ShaderStructure.hpp @@ -16,7 +16,7 @@ namespace Dawn { size_t offset; enum ShaderOpenGLStructureType structureType; size_t size; - // size_t count; + size_t count; std::vector parameters; GLint location = -1; GLuint buffer = -1; @@ -46,12 +46,14 @@ namespace Dawn { const enum ShaderOpenGLStructureType structureType, std::function< void(const T&, std::vector&) - > getParameters + > getParameters, + size_t count = 1 ) { this->structureName = structureName; this->offset = (size_t)offset; this->structureType = structureType; this->size = sizeof(T); + this->count = count; this->parameters = std::vector(); T dummy; diff --git a/src/dawnopengl/display/shader/UIShader.cpp b/src/dawnopengl/display/shader/UIShader.cpp index 34d2487b..f794439b 100644 --- a/src/dawnopengl/display/shader/UIShader.cpp +++ b/src/dawnopengl/display/shader/UIShader.cpp @@ -4,6 +4,7 @@ // https://opensource.org/licenses/MIT #include "display/shader/UIShader.hpp" +#include "util/Macro.hpp" using namespace Dawn; @@ -28,10 +29,50 @@ void UIShader::getStages( "uniform mat4 u_Projection;\n" "uniform mat4 u_View;\n" "uniform mat4 u_Model;\n" + "struct UIShaderQuad {\n" + "mat4 transform;\n" + "vec4 quad;\n" + "vec4 uv;\n" + "vec4 color;\n" + "};\n" + "layout (std140) uniform ub_Quad {\n" + "UIShaderQuad quads[" MACRO_STRINGIFY(UI_SHADER_QUAD_COUNT) "];\n" + "};\n" "out vec2 o_TextCoord;\n" + "out vec4 v_Color;\n" "void main() {\n" - "gl_Position = u_Projection * u_View * u_Model * vec4(aPos, 1.0);\n" - "o_TextCoord = vec2(aTexCoord.x, aTexCoord.y);\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" + "if(vertexIndex == 0) {\n" + "pos.x = quad.quad.x;\n" + "pos.y = quad.quad.y;\n" + "coord.x = quad.uv.x;\n" + "coord.y = quad.uv.y;\n" + "} else if(vertexIndex == 1) {\n" + "pos.x = quad.quad.z;\n" + "pos.y = quad.quad.y;\n" + "coord.x = quad.uv.z;\n" + "coord.y = quad.uv.y;\n" + "} else if(vertexIndex == 2) {\n" + "pos.y = quad.quad.w;\n" + "pos.x = quad.quad.x;\n" + "coord.x = quad.uv.x;\n" + "coord.y = quad.uv.w;\n" + "} else if(vertexIndex == 3) {\n" + "pos.x = quad.quad.z;\n" + "pos.y = quad.quad.w;\n" + "coord.x = quad.uv.z;\n" + "coord.y = quad.uv.w;\n" + "}\n" + "pos.z = 0;\n" + "pos.w = 1;\n" + "gl_Position = u_Projection * u_View * u_Model * quad.transform * pos;\n" + "o_TextCoord = coord;\n" + "v_Color = quad.color;\n" "}" ); @@ -39,14 +80,10 @@ void UIShader::getStages( ShaderStageType::FRAGMENT, "#version 330 core\n" "in vec2 o_TextCoord;\n" - "layout (std140) uniform ub_Color {\n" - "vec4 first;\n" - "vec3 random;\n" - "vec4 second;\n" - "};\n" + "in vec4 v_Color;\n" "out vec4 o_Color;\n" "void main() {\n" - "o_Color = second;\n" + "o_Color = v_Color;\n" "}\n" ); break; @@ -78,28 +115,35 @@ void UIShader::getStages( ShaderParameterType::MAT4 )); - structures.push_back(ShaderStructure( - "ub_Color", - &rel->test, + structures.push_back(ShaderStructure( + "ub_Quad", + &rel->quads, ShaderOpenGLStructureType::STD140, - [&](const struct TestStruct &rel, std::vector ¶meters) { + [&](const struct UIShaderQuad &rel, std::vector ¶meters) { parameters.push_back(ShaderParameter( - "first", - &rel.first, + "u_Transform", + &rel.transform, + ShaderParameterType::MAT4 + )); + + parameters.push_back(ShaderParameter( + "u_Quad", + &rel.quad, + ShaderParameterType::VEC4 + )); + + parameters.push_back(ShaderParameter( + "u_UV", + &rel.uv, + ShaderParameterType::VEC4 + )); + + parameters.push_back(ShaderParameter( + "u_Color", + &rel.color, ShaderParameterType::COLOR )); - - parameters.push_back(ShaderParameter( - "random", - &rel.random, - ShaderParameterType::VEC3 - )); - - parameters.push_back(ShaderParameter( - "second", - &rel.second, - ShaderParameterType::COLOR - )); - } + }, + 2 )); } \ No newline at end of file diff --git a/src/dawnopengl/display/shader/UIShader.hpp b/src/dawnopengl/display/shader/UIShader.hpp index f5f85e46..741d11d9 100644 --- a/src/dawnopengl/display/shader/UIShader.hpp +++ b/src/dawnopengl/display/shader/UIShader.hpp @@ -7,18 +7,20 @@ #include "display/shader/Shader.hpp" namespace Dawn { - struct TestStruct { - struct Color first; - glm::vec3 random; - float_t padded; - struct Color second; + #define UI_SHADER_QUAD_COUNT 32 + + struct UIShaderQuad { + glm::mat4 transform; + glm::vec4 quad; + glm::vec4 uv; + struct Color color; }; struct UIShaderData { glm::mat4 projection; glm::mat4 view; glm::mat4 model; - struct TestStruct test; + struct UIShaderQuad quads[UI_SHADER_QUAD_COUNT]; }; class UIShader : public Shader {