From 037efdd6009d1f795fea23eb693a449f97766bf5 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 17 Oct 2024 16:32:09 +0200 Subject: [PATCH] Canvas: Prepare text rendering --- contrib/assimp | 2 +- contrib/cppcore | 2 +- .../RenderBackend/2D/CanvasRenderer.cpp | 51 +++++++++- src/Engine/RenderBackend/2D/CanvasRenderer.h | 10 +- src/Engine/RenderBackend/MaterialBuilder.cpp | 94 +++++++++++++------ src/Engine/RenderBackend/MaterialBuilder.h | 1 + 6 files changed, 122 insertions(+), 38 deletions(-) diff --git a/contrib/assimp b/contrib/assimp index f81ea6986..2591d0e49 160000 --- a/contrib/assimp +++ b/contrib/assimp @@ -1 +1 @@ -Subproject commit f81ea6986ccd30a016ec44a1fd46e2e5c3ff9d4c +Subproject commit 2591d0e4902c006dd8366f1d72bf44be1c40cac6 diff --git a/contrib/cppcore b/contrib/cppcore index d4f32ce57..12b60d1fb 160000 --- a/contrib/cppcore +++ b/contrib/cppcore @@ -1 +1 @@ -Subproject commit d4f32ce57ab6bed0d78f66a85b3a4b986eee3707 +Subproject commit 12b60d1fb17774ae870b30d453fa3d9d36f74726 diff --git a/src/Engine/RenderBackend/2D/CanvasRenderer.cpp b/src/Engine/RenderBackend/2D/CanvasRenderer.cpp index 4f8bb7c20..a78d72498 100644 --- a/src/Engine/RenderBackend/2D/CanvasRenderer.cpp +++ b/src/Engine/RenderBackend/2D/CanvasRenderer.cpp @@ -119,7 +119,7 @@ CanvasRenderer::CanvasRenderer(i32 numLayers, i32 x, i32 y, i32 w, i32 h) : mNumLayers(numLayers), mFont(nullptr), mMesh(nullptr), - mTexts(nullptr) { + mFont2MeshMap() { setResolution(x, y, w, h); } @@ -141,6 +141,28 @@ void CanvasRenderer::preRender(RenderBackendService *rbSrv) { rbSrv->setMatrix(MatrixType::Projection, m); } +static void renumberIndices(const DrawCmd &dc, ui16 offset) { + if (offset > 0) { + for (size_t j = 0; j < dc.NumIndices; ++j) { + dc.Indices[j] += static_cast(offset); + } + } +} + +static bool hasTexts(const DrawCmdArray &drawCmdArray) { + if (drawCmdArray.isEmpty()) { + return true; + } + + for (size_t i = 0; i < drawCmdArray.size(); ++i) { + if (drawCmdArray[i]->UseFont != nullptr) { + return true; + } + } + + return false; +} + void CanvasRenderer::render(RenderBackendService *rbSrv) { if (rbSrv == nullptr) { return; @@ -150,6 +172,7 @@ void CanvasRenderer::render(RenderBackendService *rbSrv) { return; } + // Create not textured geometry if (mMesh == nullptr) { mMesh = new Mesh("2d", VertexType::RenderVertex, IndexType::UnsignedShort); Material *mat2D = MaterialBuilder::create2DMaterial(); @@ -160,6 +183,19 @@ void CanvasRenderer::render(RenderBackendService *rbSrv) { mMesh->setMaterial(mat2D); } + // Load all font-meshes + if (mFont2MeshMap.isEmpty()) { + if (hasTexts(mDrawCmdArray)) { + for (size_t i = 0; i < mDrawCmdArray.size(); ++i) { + const auto &dc = mDrawCmdArray[i]; + const String &keyName = dc->UseFont->Name; + const String meshName = "text." + keyName; + Material *matFont = MaterialBuilder::createTextMaterial(keyName); + + } + } + } + PrimitiveType prim = PrimitiveType::TriangleList; size_t numVertices = 0l, numIndices = 0l; for (size_t i=0; igetLastIndex(); - if (numVertices > 0) { - for (size_t j = 0; j < dc.NumIndices; ++j) { - dc.Indices[j] += static_cast(numVertices); + if (dc.UseFont != nullptr) { + const String &fontKey = dc.UseFont->Name; + Mesh *text = nullptr; + if (mFont2MeshMap.hasKey(fontKey)) { + mFont2MeshMap.getValue(fontKey, text); } + } else { } + const ui32 lastIndex = mMesh->getLastIndex(); + renumberIndices(dc, numVertices); + //Debugging::MeshDiagnostic::dumpVertices(dc.Vertices, dc.NumVertices); mMesh->attachVertices(dc.Vertices, dc.NumVertices * sizeof(RenderVert)); mMesh->attachIndices(dc.Indices, dc.NumIndices * sizeof(ui16)); diff --git a/src/Engine/RenderBackend/2D/CanvasRenderer.h b/src/Engine/RenderBackend/2D/CanvasRenderer.h index f61d2f5bf..edb639e62 100644 --- a/src/Engine/RenderBackend/2D/CanvasRenderer.h +++ b/src/Engine/RenderBackend/2D/CanvasRenderer.h @@ -24,6 +24,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "Common/osre_common.h" #include "RenderBackend/RenderCommon.h" +#include namespace OSRE { namespace RenderBackend { @@ -44,15 +45,15 @@ struct Point2Df { f32 X, Y; /// Coordinate components }; +using DrawCmdArray = cppcore::TArray; + //------------------------------------------------------------------------------------------------- /// @ingroup Engine /// /// @brief This class implements a canvas renderer. //------------------------------------------------------------------------------------------------- class OSRE_EXPORT CanvasRenderer : IRenderPath { -public: - using DrawCmdArray = cppcore::TArray; - +public: /// @brief The class constructor. /// @param numLayers The number of layers. /// @param x The x position. @@ -170,7 +171,8 @@ class OSRE_EXPORT CanvasRenderer : IRenderPath { i32 mNumLayers; Font *mFont; Mesh *mMesh; - Mesh *mTexts; + using Font2MeshMap = cppcore::THashMap; + Font2MeshMap mFont2MeshMap; }; inline void CanvasRenderer::setDirty() { diff --git a/src/Engine/RenderBackend/MaterialBuilder.cpp b/src/Engine/RenderBackend/MaterialBuilder.cpp index f77e14ca6..c03babcfa 100644 --- a/src/Engine/RenderBackend/MaterialBuilder.cpp +++ b/src/Engine/RenderBackend/MaterialBuilder.cpp @@ -51,33 +51,6 @@ static void addMaterialParameter(Material *mat) { shader->addUniformBuffer("Projection"); } -// see https://jasonliang.js.org/batch-renderer.html - const String vertex_2d = - getGLSLVersionString_400() + - getGLSLRenderVertexLayout() + - "out vec3 v_color0;\n" - "out vec2 v_texindex;\n" - "uniform mat4 Model;\n" - "uniform mat4 View;\n" - "uniform mat4 Projection;\n" - "void main() {\n" - " v_color0 = color0;\n" - " mat4 u_mvp = Projection * View * Model;\n" - " gl_Position = u_mvp * vec4(position, 1.0);\n" - " v_texindex = texcoord0;\n" - "}\n"; - -const String fragment_2d = "#version 330 core\n" - "in vec2 v_texindex;\n" - "in vec3 v_color0;\n" - "out vec4 f_color;\n" - "uniform sampler2D u_texture;\n" - "void main() {\n" - " f_color = texture(u_texture, v_texindex);\n" - " if (f_color.r==0.0 || f_color.g ==0.0 || f_color.b==0.0)\n" - " f_color = vec4(v_color0,1);\n" - "}\n"; - static constexpr c8 Render2DMat[] = "2d_mat"; Material *MaterialBuilder::create2DMaterial() { @@ -89,6 +62,31 @@ Material *MaterialBuilder::create2DMaterial() { mat = materialCache->create(Render2DMat); + const String vertex_2d = + getGLSLVersionString_400() + + getGLSLRenderVertexLayout() + + "out vec3 v_color0;\n" + "out vec2 v_texindex;\n" + "uniform mat4 Model;\n" + "uniform mat4 View;\n" + "uniform mat4 Projection;\n" + "void main() {\n" + " v_color0 = color0;\n" + " mat4 u_mvp = Projection * View * Model;\n" + " gl_Position = u_mvp * vec4(position, 1.0);\n" + " v_texindex = texcoord0;\n" + "}\n"; + const String fragment_2d = "#version 330 core\n" + "in vec2 v_texindex;\n" + "in vec3 v_color0;\n" + "out vec4 f_color;\n" + "uniform sampler2D u_texture;\n" + "void main() {\n" + " f_color = texture(u_texture, v_texindex);\n" + " if (f_color.r==0.0 || f_color.g ==0.0 || f_color.b==0.0)\n" + " f_color = vec4(v_color0,1);\n" + "}\n"; + ShaderSourceArray shArray; shArray[static_cast(ShaderType::SH_VertexShaderType)] = vertex_2d; shArray[static_cast(ShaderType::SH_FragmentShaderType)] = fragment_2d; @@ -103,6 +101,48 @@ Material *MaterialBuilder::create2DMaterial() { return mat; } +Material *MaterialBuilder::createTextMaterial(const String &fontName) { + if (fontName.empty()) { + return nullptr; + } + + MaterialBuilder::MaterialCache *materialCache = sData->mMaterialCache; + Material *mat = materialCache->find(fontName); + if (nullptr != mat) { + return mat; + } + + mat = materialCache->create(Render2DMat); + const String vertex_2d = + getGLSLVersionString_400() + + getGLSLRenderVertexLayout() + + "out vec3 v_color0;\n" + "out vec2 v_texindex;\n" + "uniform mat4 Model;\n" + "uniform mat4 View;\n" + "uniform mat4 Projection;\n" + "void main() {\n" + " v_color0 = color0;\n" + " mat4 u_mvp = Projection * View * Model;\n" + " gl_Position = u_mvp * vec4(position, 1.0);\n" + " v_texindex = texcoord0;\n" + "}\n"; + + const String fragment_2d = + "#version 330 core\n" + "in vec2 v_texindex;\n" + "in vec3 v_color0;\n" + "out vec4 f_color;\n" + "uniform sampler2D u_texture;\n" + "void main() {\n" + " f_color = texture(u_texture, v_texindex);\n" + " if (f_color.r==0.0 || f_color.g ==0.0 || f_color.b==0.0)\n" + " f_color = vec4(v_color0,1);\n" + "}\n"; + + return nullptr; +} + static const String GLSLVsSrc = getGLSLVersionString_400() + getNewLine() + diff --git a/src/Engine/RenderBackend/MaterialBuilder.h b/src/Engine/RenderBackend/MaterialBuilder.h index f89d1505d..4a87533a1 100644 --- a/src/Engine/RenderBackend/MaterialBuilder.h +++ b/src/Engine/RenderBackend/MaterialBuilder.h @@ -73,6 +73,7 @@ class OSRE_EXPORT MaterialBuilder { static RenderBackend::Material *createDebugRenderTextMaterial(); static Material *create2DMaterial(); + static Material *createTextMaterial(const String &fontName); private: /// @brief The default class constructor.