From 65aa0ad8c9441f6ba6eeeaf4e0aafd1004fbfbed Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Fri, 6 Feb 2026 18:04:16 +0300 Subject: [PATCH 01/22] gitignore: added compile commands --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 3b4cd44f5..757ee156c 100644 --- a/.gitignore +++ b/.gitignore @@ -158,7 +158,6 @@ AutoTest.Net/ # Installshield output folder [Ee]xpress/ - # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT @@ -358,3 +357,6 @@ install.json # mkdocs output site/ + +# clangd compile commands +compile_commands.json From 4a97ac49fd86beff899ae3343f210e7279868fe0 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Fri, 6 Feb 2026 22:08:02 +0300 Subject: [PATCH 02/22] CONTRIBUTING.md: fixed documentation link --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ba46db6c9..852120cd0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,3 +1,3 @@ # Contributing -See https://aui-framework.github.io/develop/md_docs_2Contributing_01to_01AUI.html +See https://aui-framework.github.io/develop/contributing/?h=contrib From 1648904197a77f6059a3a4d03802536b56b28d41 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Sat, 7 Feb 2026 17:00:00 +0300 Subject: [PATCH 03/22] editorconfig: added an editorconfig replicating clang-format --- .editorconfig | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..cb32601a7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,43 @@ +# .editorconfig +root = true + +# Apply only to C++ source and header files +[*.cpp] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true +end_of_line = lf +max_line_length = 120 + +[*.hpp] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true +end_of_line = lf +max_line_length = 120 + +[*.h] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true +end_of_line = lf +max_line_length = 120 + +[*.cc] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true +end_of_line = lf +max_line_length = 120 + +[*.cxx] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true +end_of_line = lf +max_line_length = 120 From adbe933e24642b6d4c8e5080a4790247b8e2e944 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Thu, 12 Feb 2026 21:42:50 +0300 Subject: [PATCH 04/22] batching: cmd sorting WIP --- aui.views/src/AUI/GL/IBatchingRenderer.cpp | 5 --- aui.views/src/AUI/GL/IBatchingRenderer.h | 13 ++----- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 36 ++++++++++++++++--- .../AUI/Platform/OpenGLRenderingContext.cpp | 2 +- aui.views/src/AUI/Render/ABrush.h | 2 +- 5 files changed, 36 insertions(+), 22 deletions(-) diff --git a/aui.views/src/AUI/GL/IBatchingRenderer.cpp b/aui.views/src/AUI/GL/IBatchingRenderer.cpp index 663019380..3193678f2 100644 --- a/aui.views/src/AUI/GL/IBatchingRenderer.cpp +++ b/aui.views/src/AUI/GL/IBatchingRenderer.cpp @@ -116,23 +116,18 @@ void IBatchingRenderer::squareSector(const ABrush& brush, const glm::vec2& posit } void IBatchingRenderer::pushMaskBefore() { - enqueueCommand(CmdPushMaskBefore{}); } void IBatchingRenderer::pushMaskAfter() { - enqueueCommand(CmdPushMaskAfter{}); } void IBatchingRenderer::popMaskBefore() { - enqueueCommand(CmdPopMaskBefore{}); } void IBatchingRenderer::popMaskAfter() { - enqueueCommand(CmdPopMaskAfter{}); } void IBatchingRenderer::setBlending(Blending blending) { - enqueueCommand(CmdSetBlending{.blending = blending}); } void IBatchingRenderer::flush() { diff --git a/aui.views/src/AUI/GL/IBatchingRenderer.h b/aui.views/src/AUI/GL/IBatchingRenderer.h index 57b855c6a..94d5e31d5 100644 --- a/aui.views/src/AUI/GL/IBatchingRenderer.h +++ b/aui.views/src/AUI/GL/IBatchingRenderer.h @@ -13,7 +13,7 @@ class IBatchingRenderer : public IRenderer { public: - struct CmdRectangle { + struct CmdRectangle { ABrush brush; glm::vec2 position; glm::vec2 size; @@ -81,13 +81,6 @@ class IBatchingRenderer : public IRenderer { AAngleRadians begin; AAngleRadians end; }; - struct CmdPushMaskBefore {}; - struct CmdPushMaskAfter {}; - struct CmdPopMaskBefore {}; - struct CmdPopMaskAfter {}; - struct CmdSetBlending { - Blending blending; - }; struct CmdNewRenderViewToTexture {}; struct CmdSetWindow { AWindowBase* window; @@ -97,8 +90,8 @@ class IBatchingRenderer : public IRenderer { AColor color; using Arg = std::variant< CmdRectangle, CmdRoundedRectangle, CmdRectangleBorder, CmdRoundedRectangleBorder, CmdBoxShadow, - CmdBoxShadowInner, CmdString, CmdLines, CmdPoints, CmdLinesPairs, CmdSquareSector, CmdPushMaskBefore, CmdPushMaskAfter, CmdPopMaskBefore, CmdPopMaskAfter, - CmdSetBlending, CmdNewRenderViewToTexture, CmdSetWindow>; + CmdBoxShadowInner, CmdString, CmdLines, CmdPoints, CmdLinesPairs, CmdSquareSector, + CmdNewRenderViewToTexture, CmdSetWindow>; Arg arg; }; diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index cb9195c07..5ed2f3fea 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -13,6 +13,7 @@ // Created by Alex2772 on 11/19/2021. // +#include #include #include "OpenGLRenderer.h" #include "AUI/Common/AException.h" @@ -20,12 +21,14 @@ #include "AUI/GL/Framebuffer.h" #include "AUI/GL/GLDebug.h" #include "AUI/GL/GLEnums.h" +#include "AUI/GL/IBatchingRenderer.h" #include "AUI/GL/Program.h" #include "AUI/GL/Texture2D.h" #include "AUI/GL/Vao.h" #include "AUI/Platform/AInput.h" #include "AUI/Platform/APlatform.h" #include "AUI/Render/ABorderStyle.h" +#include "AUI/Render/ABrush.h" #include "AUI/Render/Brush/Gradient.h" #include "AUI/Render/IRenderer.h" #include "AUI/Util/AAngleRadians.h" @@ -62,6 +65,7 @@ #include #include #include +#include static constexpr auto LOG_TAG = "OpenGLRenderer"; @@ -239,7 +243,34 @@ OpenGLRenderer::OpenGLRenderer() { } } +static int getBrushIndex(const IBatchingRenderer::Cmd& cmd) { + int result = -1; + + std::visit(aui::lambda_overloaded { + [&](const IBatchingRenderer::CmdRectangle& arg) { result = arg.brush.index(); }, + [&](const IBatchingRenderer::CmdRoundedRectangle& arg) { result = arg.brush.index(); }, + [&](const IBatchingRenderer::CmdRectangleBorder& arg) { result = arg.brush.index(); }, + [&](const IBatchingRenderer::CmdRoundedRectangleBorder& arg) { result = arg.brush.index(); }, + [&](const IBatchingRenderer::CmdLines& arg) { result = arg.brush.index(); }, + [&](const IBatchingRenderer::CmdPoints& arg) { result = arg.brush.index(); }, + [&](const IBatchingRenderer::CmdLinesPairs& arg) { result = arg.brush.index(); }, + [&](const IBatchingRenderer::CmdSquareSector& arg) { result = arg.brush.index(); }, + [&](const IBatchingRenderer::CmdSetWindow& arg) { result = -2; }, + [&](const auto& arg) { }, + }, cmd.arg); + + return result; +} + void OpenGLRenderer::handleCmds(std::vector cmds) { + std::sort(cmds.begin(), cmds.end(), [](const Cmd& cmdA, const Cmd& cmdB) { + if (cmdA.arg.index() != cmdB.arg.index()) { + return cmdA.arg.index() > cmdB.arg.index(); + } + + return getBrushIndex(cmdA) > getBrushIndex(cmdB); + }); + for (auto& cmd : cmds) { std::visit(aui::lambda_overloaded{ [&](const CmdRectangle& c) { renderRectangle(cmd, c.brush, c.position, c.size); }, @@ -253,11 +284,6 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { [&](const CmdPoints& c) { renderPoints(cmd, c.brush, c.points, c.size); }, [&](const CmdLinesPairs& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, [&](const CmdSquareSector& c) { renderSquareSector(cmd, c.brush, c.position, c.size, c.begin, c.end); }, - [&](const CmdPushMaskBefore&) { renderPushMaskBefore(); }, - [&](const CmdPopMaskBefore&) { renderPopMaskBefore(); }, - [&](const CmdPushMaskAfter&) { renderPushMaskAfter(); }, - [&](const CmdPopMaskAfter&) { renderPopMaskAfter(); }, - [&](const CmdSetBlending& c) { renderSetBlending(c.blending); }, [&](const CmdSetWindow& c) { mWindow = c.window; }, [&](const CmdNewRenderViewToTexture&){ /* handled elsewhere */ } }, cmd.arg); diff --git a/aui.views/src/AUI/Platform/OpenGLRenderingContext.cpp b/aui.views/src/AUI/Platform/OpenGLRenderingContext.cpp index f291c3a16..b29acd41e 100644 --- a/aui.views/src/AUI/Platform/OpenGLRenderingContext.cpp +++ b/aui.views/src/AUI/Platform/OpenGLRenderingContext.cpp @@ -83,4 +83,4 @@ uint32_t OpenGLRenderingContext::getSupersamplingRatio() const noexcept { return fb->supersamlingRatio(); } return 1; -} \ No newline at end of file +} diff --git a/aui.views/src/AUI/Render/ABrush.h b/aui.views/src/AUI/Render/ABrush.h index d15f8dba2..9716c1021 100644 --- a/aui.views/src/AUI/Render/ABrush.h +++ b/aui.views/src/AUI/Render/ABrush.h @@ -110,4 +110,4 @@ struct ATexturedBrush { using ABrush = std::variant; \ No newline at end of file + ACustomShaderBrush>; From 28cb69242635d598ffe181ca2c8062288f0851fb Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Sat, 14 Feb 2026 01:43:35 +0300 Subject: [PATCH 05/22] batching: cmd sorting --- .editorconfig | 34 +------------- aui.views/src/AUI/GL/IBatchingRenderer.h | 11 +++++ aui.views/src/AUI/GL/OpenGLRenderer.cpp | 58 ++++++++++++++---------- 3 files changed, 47 insertions(+), 56 deletions(-) diff --git a/.editorconfig b/.editorconfig index cb32601a7..d6bbf8031 100644 --- a/.editorconfig +++ b/.editorconfig @@ -2,39 +2,7 @@ root = true # Apply only to C++ source and header files -[*.cpp] -indent_style = space -indent_size = 4 -trim_trailing_whitespace = true -insert_final_newline = true -end_of_line = lf -max_line_length = 120 - -[*.hpp] -indent_style = space -indent_size = 4 -trim_trailing_whitespace = true -insert_final_newline = true -end_of_line = lf -max_line_length = 120 - -[*.h] -indent_style = space -indent_size = 4 -trim_trailing_whitespace = true -insert_final_newline = true -end_of_line = lf -max_line_length = 120 - -[*.cc] -indent_style = space -indent_size = 4 -trim_trailing_whitespace = true -insert_final_newline = true -end_of_line = lf -max_line_length = 120 - -[*.cxx] +[*.{cpp,hpp,h,cc,cxx}] indent_style = space indent_size = 4 trim_trailing_whitespace = true diff --git a/aui.views/src/AUI/GL/IBatchingRenderer.h b/aui.views/src/AUI/GL/IBatchingRenderer.h index 94d5e31d5..8c8a07b74 100644 --- a/aui.views/src/AUI/GL/IBatchingRenderer.h +++ b/aui.views/src/AUI/GL/IBatchingRenderer.h @@ -9,6 +9,7 @@ #pragma once +#include #include "AUI/Render/IRenderer.h" class IBatchingRenderer : public IRenderer { @@ -85,6 +86,13 @@ class IBatchingRenderer : public IRenderer { struct CmdSetWindow { AWindowBase* window; }; + union BatchId { + struct { + unsigned int cmdId : 8; + unsigned int brushId : 8; + }; + u_int16_t value; + }; struct Cmd { glm::mat4 transform; AColor color; @@ -93,6 +101,8 @@ class IBatchingRenderer : public IRenderer { CmdBoxShadowInner, CmdString, CmdLines, CmdPoints, CmdLinesPairs, CmdSquareSector, CmdNewRenderViewToTexture, CmdSetWindow>; Arg arg; + int zIndex; + BatchId batchId; }; ~IBatchingRenderer() override = default; @@ -127,6 +137,7 @@ class IBatchingRenderer : public IRenderer { .transform = getTransform(), .color = getColor(), .arg = std::move(arg), + .zIndex = static_cast(mCmds.size()) }); } diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index 5ed2f3fea..75ed347f5 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -14,6 +14,8 @@ // #include +#include +#include #include #include "OpenGLRenderer.h" #include "AUI/Common/AException.h" @@ -64,6 +66,7 @@ #include #include #include +#include #include #include @@ -243,19 +246,20 @@ OpenGLRenderer::OpenGLRenderer() { } } -static int getBrushIndex(const IBatchingRenderer::Cmd& cmd) { - int result = -1; +static unsigned int getBrushIndex(const IBatchingRenderer::Cmd& cmd) { + unsigned int result = 1; + const int offset = 3; std::visit(aui::lambda_overloaded { - [&](const IBatchingRenderer::CmdRectangle& arg) { result = arg.brush.index(); }, - [&](const IBatchingRenderer::CmdRoundedRectangle& arg) { result = arg.brush.index(); }, - [&](const IBatchingRenderer::CmdRectangleBorder& arg) { result = arg.brush.index(); }, - [&](const IBatchingRenderer::CmdRoundedRectangleBorder& arg) { result = arg.brush.index(); }, - [&](const IBatchingRenderer::CmdLines& arg) { result = arg.brush.index(); }, - [&](const IBatchingRenderer::CmdPoints& arg) { result = arg.brush.index(); }, - [&](const IBatchingRenderer::CmdLinesPairs& arg) { result = arg.brush.index(); }, - [&](const IBatchingRenderer::CmdSquareSector& arg) { result = arg.brush.index(); }, - [&](const IBatchingRenderer::CmdSetWindow& arg) { result = -2; }, + [&](const IBatchingRenderer::CmdRectangle& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdRoundedRectangle& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdRectangleBorder& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdRoundedRectangleBorder& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdLines& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdPoints& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdLinesPairs& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdSquareSector& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdSetWindow& arg) { result = offset - 1; }, [&](const auto& arg) { }, }, cmd.arg); @@ -263,14 +267,17 @@ static int getBrushIndex(const IBatchingRenderer::Cmd& cmd) { } void OpenGLRenderer::handleCmds(std::vector cmds) { + for (auto& cmd : cmds) { + cmd.batchId = { + .cmdId = static_cast(cmd.arg.index()), + .brushId = getBrushIndex(cmd) + }; + } std::sort(cmds.begin(), cmds.end(), [](const Cmd& cmdA, const Cmd& cmdB) { - if (cmdA.arg.index() != cmdB.arg.index()) { - return cmdA.arg.index() > cmdB.arg.index(); - } - - return getBrushIndex(cmdA) > getBrushIndex(cmdB); + return cmdA.batchId.value > cmdB.batchId.value; }); + u_int16_t currentBatchId; for (auto& cmd : cmds) { std::visit(aui::lambda_overloaded{ [&](const CmdRectangle& c) { renderRectangle(cmd, c.brush, c.position, c.size); }, @@ -287,6 +294,18 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { [&](const CmdSetWindow& c) { mWindow = c.window; }, [&](const CmdNewRenderViewToTexture&){ /* handled elsewhere */ } }, cmd.arg); + + u_int16_t nextId = cmd.batchId.value + 1; // + 1 so 0 ID cmd 0 ID brush != NULL + if (!currentBatchId) { + currentBatchId = nextId; + continue; + } + // TODO: don't draw for non drawing commands like set window + if (currentBatchId == nextId) + continue; +mRectangleVao.drawElements(); + // TODO: Add drawArrays for points and lines support + currentBatchId = nextId; } } @@ -334,8 +353,6 @@ void OpenGLRenderer::drawRectImpl(glm::vec2 position, glm::vec2 size) { mRectangleVao.bind(); mRectangleVao.insert(0, AArrayView(getVerticesForRect(position, size)), "drawRectImpl"); - - mRectangleVao.drawElements(); } void OpenGLRenderer::identityUv() { @@ -403,7 +420,6 @@ void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, }), "rectangleBorder"); glLineWidth(lineWidth); - mRectangleVao.drawElements(GL_LINES); } void OpenGLRenderer::renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& brush, @@ -463,8 +479,6 @@ void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, {w, y}, }; mRectangleVao.insert(0, AArrayView(uvs), "boxShadow"); - - mRectangleVao.drawElements(); } void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, @@ -500,8 +514,6 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, {w, y}, }; mRectangleVao.insert(0, AArrayView(uvs), "boxShadowInner"); - - mRectangleVao.drawElements(); } void OpenGLRenderer::renderString(const Cmd& cmd, glm::vec2 position, From 7fd87f75c6ebe4ad58eac7c61387653ebc1e335a Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Sat, 14 Feb 2026 13:58:59 +0300 Subject: [PATCH 06/22] batching: fixed BatchingId type --- aui.views/src/AUI/GL/IBatchingRenderer.h | 8 ++++---- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/aui.views/src/AUI/GL/IBatchingRenderer.h b/aui.views/src/AUI/GL/IBatchingRenderer.h index 8c8a07b74..99ac5bcb0 100644 --- a/aui.views/src/AUI/GL/IBatchingRenderer.h +++ b/aui.views/src/AUI/GL/IBatchingRenderer.h @@ -9,7 +9,7 @@ #pragma once -#include +#include #include "AUI/Render/IRenderer.h" class IBatchingRenderer : public IRenderer { @@ -88,10 +88,10 @@ class IBatchingRenderer : public IRenderer { }; union BatchId { struct { - unsigned int cmdId : 8; - unsigned int brushId : 8; + unsigned char cmdId : 8; + unsigned char brushId : 8; }; - u_int16_t value; + uint16_t value; }; struct Cmd { glm::mat4 transform; diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index 75ed347f5..b152dcc96 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -14,6 +14,7 @@ // #include +#include #include #include #include @@ -246,7 +247,7 @@ OpenGLRenderer::OpenGLRenderer() { } } -static unsigned int getBrushIndex(const IBatchingRenderer::Cmd& cmd) { +static unsigned char getBrushIndex(const IBatchingRenderer::Cmd& cmd) { unsigned int result = 1; const int offset = 3; @@ -269,7 +270,7 @@ static unsigned int getBrushIndex(const IBatchingRenderer::Cmd& cmd) { void OpenGLRenderer::handleCmds(std::vector cmds) { for (auto& cmd : cmds) { cmd.batchId = { - .cmdId = static_cast(cmd.arg.index()), + .cmdId = static_cast(cmd.arg.index()), .brushId = getBrushIndex(cmd) }; } @@ -277,7 +278,7 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { return cmdA.batchId.value > cmdB.batchId.value; }); - u_int16_t currentBatchId; + uint16_t currentBatchId; for (auto& cmd : cmds) { std::visit(aui::lambda_overloaded{ [&](const CmdRectangle& c) { renderRectangle(cmd, c.brush, c.position, c.size); }, From a404d4d38b2e3b24f5f82d8b5e3f6543d4d1ff77 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Sat, 14 Feb 2026 14:02:12 +0300 Subject: [PATCH 07/22] openglrenderer: fixed getBrushIndex types --- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index b152dcc96..729b92e9e 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -248,8 +248,8 @@ OpenGLRenderer::OpenGLRenderer() { } static unsigned char getBrushIndex(const IBatchingRenderer::Cmd& cmd) { - unsigned int result = 1; - const int offset = 3; + unsigned char result = 1; + const char offset = 3; std::visit(aui::lambda_overloaded { [&](const IBatchingRenderer::CmdRectangle& arg) { result = arg.brush.index() + offset; }, From c995471d586f508a3bf7f42797c4f16fdf080ca1 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Sat, 14 Feb 2026 15:53:32 +0300 Subject: [PATCH 08/22] cmake: added AUI_ENABLE_UBSAN flag --- aui.core/CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/aui.core/CMakeLists.txt b/aui.core/CMakeLists.txt index 0f95fdcca..a0655454c 100644 --- a/aui.core/CMakeLists.txt +++ b/aui.core/CMakeLists.txt @@ -3,6 +3,7 @@ cmake_minimum_required(VERSION 3.16) option(AUI_CATCH_UNHANDLED "Catch segfault" ON) option(AUI_COROUTINES "Use C++20 coroutines" OFF) option(AUI_ENABLE_ASAN "Enable AddressSanitizer" OFF) +option(AUI_ENABLE_UBSAN "Enable UndefinedBehaviourSanitizer" OFF) option(AUI_ENABLE_DEATH_TESTS "Enable GTest death tests" ON) aui_module(aui.core EXPORT aui) @@ -194,6 +195,12 @@ if (AUI_ENABLE_ASAN) target_link_options(aui.core PUBLIC -fsanitize=address) endif() +if (AUI_ENABLE_UBSAN) + message(STATUS "AUI_ENABLE_UBSAN=${AUI_ENABLE_UBSAN}") + target_compile_options(aui.core PUBLIC -fsanitize=undefined) + target_link_options(aui.core PUBLIC -fsanitize=undefined) +endif() + if(MSVC) target_compile_options(aui.core PUBLIC /bigobj) endif() From e322997aec03e01350052982207fbcf5aef9b0e5 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Sun, 15 Feb 2026 19:01:48 +0300 Subject: [PATCH 09/22] batching: render command adjustments WIP --- aui.views/src/AUI/GL/IBatchingRenderer.cpp | 17 ++- aui.views/src/AUI/GL/IBatchingRenderer.h | 6 + aui.views/src/AUI/GL/OpenGLRenderer.cpp | 150 +++++++++++++-------- aui.views/src/AUI/GL/OpenGLRenderer.h | 23 +++- aui.views/src/AUI/GL/Vao.cpp | 9 +- aui.views/src/AUI/GL/Vao.h | 19 ++- 6 files changed, 145 insertions(+), 79 deletions(-) diff --git a/aui.views/src/AUI/GL/IBatchingRenderer.cpp b/aui.views/src/AUI/GL/IBatchingRenderer.cpp index 3193678f2..b058e1a0a 100644 --- a/aui.views/src/AUI/GL/IBatchingRenderer.cpp +++ b/aui.views/src/AUI/GL/IBatchingRenderer.cpp @@ -15,9 +15,10 @@ void IBatchingRenderer::rectangle(const ABrush& brush, glm::vec2 position, glm::vec2 size) { enqueueCommand(CmdRectangle { - .brush = std::move(brush), - .position = position, - .size = size, + .brush = std::move(brush), + .position = position, + .size = size, + .zIndex = static_cast(mCmds.size()) + 1 }); } @@ -27,6 +28,7 @@ void IBatchingRenderer::roundedRectangle(const ABrush& brush, glm::vec2 position .position = position, .size = size, .radius = radius, + .zIndex = static_cast(mCmds.size()) + 1 }); } @@ -36,6 +38,7 @@ void IBatchingRenderer::rectangleBorder(const ABrush& brush, glm::vec2 position, .position = position, .size = size, .lineWidth = lineWidth, + .zIndex = static_cast(mCmds.size()) + 1 }); } @@ -46,6 +49,7 @@ void IBatchingRenderer::roundedRectangleBorder(const ABrush& brush, glm::vec2 po .size = size, .radius = radius, .borderWidth = borderWidth, + .zIndex = static_cast(mCmds.size()) + 1 }); } @@ -55,6 +59,7 @@ void IBatchingRenderer::boxShadow(glm::vec2 position, glm::vec2 size, float blur .size = size, .blurRadius = blurRadius, .color = color, + .zIndex = static_cast(mCmds.size()) + 1 }); } @@ -67,6 +72,7 @@ void IBatchingRenderer::boxShadowInner(glm::vec2 position, glm::vec2 size, float .borderRadius = borderRadius, .color = color, .offset = offset, + .zIndex = static_cast(mCmds.size()) + 1 }); } @@ -116,18 +122,23 @@ void IBatchingRenderer::squareSector(const ABrush& brush, const glm::vec2& posit } void IBatchingRenderer::pushMaskBefore() { + // TODO: move to cmds } void IBatchingRenderer::pushMaskAfter() { + // TODO: move to cmds } void IBatchingRenderer::popMaskBefore() { + // TODO: move to cmds } void IBatchingRenderer::popMaskAfter() { + // TODO: move to cmds } void IBatchingRenderer::setBlending(Blending blending) { + // TODO: move to cmds } void IBatchingRenderer::flush() { diff --git a/aui.views/src/AUI/GL/IBatchingRenderer.h b/aui.views/src/AUI/GL/IBatchingRenderer.h index 99ac5bcb0..03821a957 100644 --- a/aui.views/src/AUI/GL/IBatchingRenderer.h +++ b/aui.views/src/AUI/GL/IBatchingRenderer.h @@ -18,18 +18,21 @@ class IBatchingRenderer : public IRenderer { ABrush brush; glm::vec2 position; glm::vec2 size; + int zIndex; }; struct CmdRoundedRectangle { ABrush brush; glm::vec2 position; glm::vec2 size; float radius; + int zIndex; }; struct CmdRectangleBorder { ABrush brush; glm::vec2 position; glm::vec2 size; float lineWidth; + int zIndex; }; struct CmdRoundedRectangleBorder { ABrush brush; @@ -37,12 +40,14 @@ class IBatchingRenderer : public IRenderer { glm::vec2 size; float radius; int borderWidth; + int zIndex; }; struct CmdBoxShadow { glm::vec2 position; glm::vec2 size; float blurRadius; AColor color; + int zIndex; }; struct CmdBoxShadowInner { glm::vec2 position; @@ -52,6 +57,7 @@ class IBatchingRenderer : public IRenderer { float borderRadius; AColor color; glm::vec2 offset; + int zIndex; }; struct CmdString { glm::vec2 position; diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index 729b92e9e..06fc19ca4 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -69,6 +69,7 @@ #include #include #include +#include #include static constexpr auto LOG_TAG = "OpenGLRenderer"; @@ -140,7 +141,7 @@ void texturedBrush(const IBatchingRenderer::Cmd& cmd, const ATexturedBrush& brus {uv1.x, uv1.y}, {uv2.x, uv1.y}, }; - tempVao.insert(1, AArrayView(uvs), "TexturedShaderHelper"); + tempVao.insert(1, std::span{uvs}, "TexturedShaderHelper"); } else { renderer.identityUv(); } @@ -238,13 +239,15 @@ OpenGLRenderer::OpenGLRenderer() { aui::sl_gen::line_solid_dashed::fsh::glsl120::Shader>(mLineSolidDashedShader); { - constexpr GLuint INDICES[] = {0, 1, 2, 2, 1, 3}; - mRectangleVao.indices(INDICES); + GLuint INDICES[] = {0, 1, 2, 2, 1, 3}; + mRectangleVao.indices(std::span{INDICES}); } { - constexpr GLuint INDICES[] = {0, 1, 2, 3, 4, 5, 6, 7}; - mBorderVao.indices(INDICES); + GLuint INDICES[] = {0, 1, 2, 3, 4, 5, 6, 7}; + mBorderVao.indices(std::span{INDICES}); } + mBatchVerticies.fill(glm::vec3{0}); + mCurrentBatchVertex = mBatchVerticies.begin(); } static unsigned char getBrushIndex(const IBatchingRenderer::Cmd& cmd) { @@ -274,19 +277,21 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { .brushId = getBrushIndex(cmd) }; } - std::sort(cmds.begin(), cmds.end(), [](const Cmd& cmdA, const Cmd& cmdB) { + std::ranges::sort(cmds, [](const Cmd& cmdA, const Cmd& cmdB) { return cmdA.batchId.value > cmdB.batchId.value; }); uint16_t currentBatchId; + bool breakBatch = false; for (auto& cmd : cmds) { + // TODO: add logic here so the batch breaks if BATCH_VERTEX_AMOUNT will be exceeded std::visit(aui::lambda_overloaded{ - [&](const CmdRectangle& c) { renderRectangle(cmd, c.brush, c.position, c.size); }, - [&](const CmdRoundedRectangle& c) { renderRoundedRectangle(cmd, c.brush, c.position, c.size, c.radius); }, - [&](const CmdRectangleBorder& c) { renderRectangleBorder(cmd, c.brush, c.position, c.size, c.lineWidth); }, - [&](const CmdRoundedRectangleBorder& c) { renderRoundedRectangleBorder(cmd, c.brush, c.position, c.size, c.radius, c.borderWidth); }, - [&](const CmdBoxShadow& c) { renderBoxShadow(cmd, c.position, c.size, c.blurRadius, c.color); }, - [&](const CmdBoxShadowInner& c) { renderBoxShadowInner(cmd, c.position, c.size, c.blurRadius, c.spreadRadius, c.borderRadius, c.color, c.offset); }, + [&](const CmdRectangle& c) { renderRectangle(cmd, c.brush, c.position, c.size, c.zIndex); }, + [&](const CmdRoundedRectangle& c) { renderRoundedRectangle(cmd, c.brush, c.position, c.size, c.radius, c.zIndex); }, + [&](const CmdRectangleBorder& c) { renderRectangleBorder(cmd, c.brush, c.position, c.size, c.lineWidth, c.zIndex); }, + [&](const CmdRoundedRectangleBorder& c) { renderRoundedRectangleBorder(cmd, c.brush, c.position, c.size, c.radius, c.borderWidth, c.zIndex); }, + [&](const CmdBoxShadow& c) { renderBoxShadow(cmd, c.position, c.size, c.blurRadius, c.color, c.zIndex); }, + [&](const CmdBoxShadowInner& c) { renderBoxShadowInner(cmd, c.position, c.size, c.blurRadius, c.spreadRadius, c.borderRadius, c.color, c.offset, c.zIndex); }, [&](const CmdString& c) { renderString(cmd, c.position, c.string, c.fs); }, [&](const CmdLines& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, [&](const CmdPoints& c) { renderPoints(cmd, c.brush, c.points, c.size); }, @@ -302,11 +307,16 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { continue; } // TODO: don't draw for non drawing commands like set window - if (currentBatchId == nextId) + breakBatch = breakBatch or (currentBatchId != nextId); + if (not breakBatch) continue; -mRectangleVao.drawElements(); - // TODO: Add drawArrays for points and lines support + + mRectangleVao.insert(0, std::span{mBatchVerticies}, "Batch"); + mRectangleVao.drawElements(); currentBatchId = nextId; + + std::ranges::fill(mBatchVerticies, glm::vec3(0)); + mCurrentBatchVertex = mBatchVerticies.begin(); } } @@ -332,7 +342,25 @@ std::array OpenGLRenderer::getVerticesForRect(glm::vec2 position, }; } -void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size) { +void OpenGLRenderer::appendBatchVerticiesForRect(const glm::vec2 position, const glm::vec2 size, const int zIndex) { + float x = position.x; + float y = position.y; + float z = zIndex; + float w = x + size.x; + float h = y + size.y; + + std::array verticies { + glm::vec3 { x, h, z }, + glm::vec3 { w, h, z }, + glm::vec3 { x, y, z }, + glm::vec3 { w, y, z }, + }; + + std::ranges::copy(verticies, mCurrentBatchVertex); + mCurrentBatchVertex += mQuadVertexCount; +} + +void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const int zIndex) { std::visit(aui::lambda_overloaded{ [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); @@ -347,13 +375,13 @@ void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::v }, brush); gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, cmd.transform); - drawRectImpl(position, size); + drawRectImpl(position, size, zIndex); } -void OpenGLRenderer::drawRectImpl(glm::vec2 position, glm::vec2 size) { +void OpenGLRenderer::drawRectImpl(const glm::vec2 position, const glm::vec2 size, const int zIndex) { mRectangleVao.bind(); - mRectangleVao.insert(0, AArrayView(getVerticesForRect(position, size)), "drawRectImpl"); + appendBatchVerticiesForRect(position, size, zIndex); } void OpenGLRenderer::identityUv() { @@ -363,13 +391,14 @@ void OpenGLRenderer::identityUv() { {0, 0}, {1, 0} }; - mRectangleVao.insertIfKeyMismatches(1, AArrayView(uvs), "identityUv"); + mRectangleVao.insertIfKeyMismatches(1, std::span{uvs}, "identityUv"); } void OpenGLRenderer::renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, - float radius) { + float radius, + const int zIndex) { std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mRoundedGradientShader); }, @@ -380,13 +409,14 @@ void OpenGLRenderer::renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, identityUv(); gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_SIZE, 2.f * radius / size); - drawRectImpl(position, size); + drawRectImpl(position, size, zIndex); } void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, - float lineWidth) { + float lineWidth, + const int zIndex) { std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, @@ -404,21 +434,21 @@ void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, float y = position.y; float w = x + size.x; float h = y + size.y; + std::array verticies = std::array { + glm::vec3(glm::vec4 { x + lineWidth, y + lineDelta, 1, 1 }), + glm::vec3(glm::vec4 { w, y + lineDelta, 1, 1 }), - mRectangleVao.insert(0, - AArrayView(std::array{ - glm::vec3(glm::vec4{x + lineWidth, y + lineDelta, 1, 1}), - glm::vec3(glm::vec4{w, y + lineDelta, 1, 1}), + glm::vec3(glm::vec4 { w - lineDelta, y + lineWidth, 1, 1 }), + glm::vec3(glm::vec4 { w - lineDelta, h, 1, 1 }), - glm::vec3(glm::vec4{w - lineDelta, y + lineWidth, 1, 1}), - glm::vec3(glm::vec4{w - lineDelta, h, 1, 1}), + glm::vec3(glm::vec4 { w - lineWidth, h - lineDelta - 0.15f, 1, 1 }), + glm::vec3(glm::vec4 { x, h - lineDelta - 0.15f, 1, 1 }), - glm::vec3(glm::vec4{w - lineWidth, h - lineDelta - 0.15f, 1, 1}), - glm::vec3(glm::vec4{x, h - lineDelta - 0.15f, 1, 1}), + glm::vec3(glm::vec4 { x + lineDelta, h - lineWidth - 0.15f, 1, 1 }), + glm::vec3(glm::vec4 { x + lineDelta, y, 1, 1 }) + }; - glm::vec3(glm::vec4{x + lineDelta, h - lineWidth - 0.15f, 1, 1}), - glm::vec3(glm::vec4{x + lineDelta, y, 1, 1}), - }), "rectangleBorder"); + mRectangleVao.insert(0, std::span{verticies}, "rectangleBorder"); glLineWidth(lineWidth); } @@ -427,7 +457,8 @@ void OpenGLRenderer::renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& glm::vec2 position, glm::vec2 size, float radius, - int borderWidth) { + int borderWidth, + const int zIndex) { std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, @@ -444,13 +475,14 @@ void OpenGLRenderer::renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& gl::Program::currentShader()->set(aui::ShaderUniforms::INNER_SIZE, 2.f * (radius - borderWidth) / innerSize); gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_TO_INNER, size / innerSize); gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, cmd.transform); - drawRectImpl(position, size); + drawRectImpl(position, size, zIndex); } void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, glm::vec2 size, float blurRadius, - const AColor& color) { + const AColor& color, + const int zIndex) { AUI_ASSERTX(blurRadius >= 0.f, "blurRadius is expected to be non negative, use boxShadowInner for inset shadows instead"); identityUv(); @@ -479,7 +511,8 @@ void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, {x, y}, {w, y}, }; - mRectangleVao.insert(0, AArrayView(uvs), "boxShadow"); + + mRectangleVao.insert(0, std::span{uvs}, "boxShadowInner"); } void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, @@ -488,7 +521,8 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, float spreadRadius, float borderRadius, const AColor& color, - glm::vec2 offset) { + glm::vec2 offset, + const int zIndex) { AUI_ASSERTX(blurRadius >= 0.f, "blurRadius is expected to be non negative"); blurRadius *= -1.f; identityUv(); @@ -514,7 +548,8 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, {x, y}, {w, y}, }; - mRectangleVao.insert(0, AArrayView(uvs), "boxShadowInner"); + + mRectangleVao.insert(0, std::span{uvs}, "boxShadowInner"); } void OpenGLRenderer::renderString(const Cmd& cmd, glm::vec2 position, @@ -956,7 +991,7 @@ void OpenGLRenderer::renderLines(const Cmd& cmd, const ABrush& brush, AArrayView positions << LineVertex{point, distanceAccumulator, 1.f}; } - mRectangleVao.insert(0, AArrayView(positions), "lines"); + mRectangleVao.insert(0, std::span{positions}, "lines"); mRectangleVao.drawArrays(GL_LINE_STRIP, points.size()); } @@ -985,7 +1020,7 @@ void OpenGLRenderer::renderLines(const Cmd& cmd, const ABrush& brush, AArrayView }; } - mRectangleVao.insert(0, AArrayView(positions), "lines"); + mRectangleVao.insert(0, std::span{positions}, "lines"); mRectangleVao.drawArrays(GL_LINES, positions.size()); } @@ -1015,7 +1050,7 @@ void OpenGLRenderer::renderPoints(const Cmd& cmd, const ABrush& brush, AArrayVie glPointSize(widthPx); mRectangleVao.bind(); - mRectangleVao.insert(0, AArrayView(points), "points"); + mRectangleVao.insert(0, std::span{points}, "lines"); mRectangleVao.drawArrays(GL_POINTS, points.size()); #endif } @@ -1049,7 +1084,8 @@ void OpenGLRenderer::renderSquareSector(const Cmd& cmd, const ABrush& brush, gl::Program::currentShader()->set(aui::ShaderUniforms::M1, m1); gl::Program::currentShader()->set(aui::ShaderUniforms::M2, m2); - drawRectImpl(position, size); + // TODO: replace 0 with zIndex + drawRectImpl(position, size, 0); } @@ -1178,7 +1214,7 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept auto vertices = ranges::views::transform(*rectangles, [&](const ARect& r) { return getVerticesForRect(r.p1, r.size()); }) | ranges::views::join | ranges::to(); - mRenderer.mRectangleVao.insert(0, AArrayView(vertices), "render-to-texture invalid areas"); + mRenderer.mRectangleVao.insert(0, std::span(vertices), "render-to-texture invalid areas"); auto indices = ranges::views::generate([i = 0]() mutable { int offset = 4 * i++; return std::array{GLuint(offset + 0), @@ -1192,10 +1228,10 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept | ranges::to() ; static constexpr auto DEFAULT_INDICES_SIZE = 6; - if (indices.size() != DEFAULT_INDICES_SIZE) mRenderer.mRectangleVao.indices(AArrayView(indices)); + if (indices.size() != DEFAULT_INDICES_SIZE) mRenderer.mRectangleVao.indices(std::span{indices}); AUI_DEFER { if (indices.size() != DEFAULT_INDICES_SIZE) { - mRenderer.mRectangleVao.indices(AArrayView(indices.data(), 6)); + mRenderer.mRectangleVao.indices(std::span{indices.data(),6 }); } }; mRenderer.mSolidShader->use(); @@ -1246,8 +1282,8 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept {0, 1}, {1, 1} }; - mRenderer.mRectangleVao.insertIfKeyMismatches(1, AArrayView(uvs), "OpenGLRenderViewToTexture"); - mRenderer.drawRectImpl({0, 0}, mFramebuffer.size()); + mRenderer.mRectangleVao.insertIfKeyMismatches(1, std::span{uvs}, "OpenGLRenderViewToTexture"); + // mRenderer.drawRectImpl({0, 0}, mFramebuffer.size()); if (auto& p = AWindow::current()->profiling(); p && p->renderToTextureDecay) [[unlikely]] { // decays to fast. attach it to time using namespace std::chrono; @@ -1277,7 +1313,7 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept shader->use(); shader->set(aui::ShaderUniforms::TRANSFORM, glm::mat4(1.f)); shader->set(aui::ShaderUniforms::COLOR, glm::vec4(0.5, 0.5, 0.5, 0.1)); - mRenderer.drawRectImpl({-1, -1}, {2, 2}); // offscreen + // mRenderer.drawRectImpl({-1, -1}, {2, 2}); // offscreen } } @@ -1447,7 +1483,8 @@ void main() { identityUv(); glDisable(GL_BLEND); - drawRectImpl({}, size); + // TODO: replace 0 with zIndex + drawRectImpl({}, size, 0); glEnable(GL_BLEND); areaOfInterest = AreaOfInterest { @@ -1541,7 +1578,8 @@ void main() {{ } gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, mTransform); identityUv(); - drawRectImpl({}, sizeDownscaled); + // TODO: Replace 0 with zIndex + drawRectImpl({}, sizeDownscaled, 0); areaOfInterest.reset(); // release borrowed framebuffer before requesting another one @@ -1565,7 +1603,8 @@ void main() {{ stepSize / 2.f); } gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, mTransform); - drawRectImpl({}, sizeDownscaled); + // TODO: replace 0 with zIndex + drawRectImpl({}, sizeDownscaled, 0); areaOfInterest = AreaOfInterest { .framebuffer = std::move(offscreen2), @@ -1590,7 +1629,7 @@ void main() {{ { 0, uv.y }, { uv.x, uv.y }, }; - mRectangleVao.insertIfKeyMismatches(1, AArrayView(uvs), "backdrops"); + mRectangleVao.insertIfKeyMismatches(1, std::span{uvs}, "backdrops"); } auto& texture = areaOfInterest->framebuffer->rendertarget->texture(); @@ -1599,7 +1638,8 @@ void main() {{ texture.setupLinear(); gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, mTransform); - drawRectImpl(position, size); + // TODO: replace 0 with zIndex + drawRectImpl(position, size, 0); } OpenGLRenderer::FramebufferFromPool OpenGLRenderer::getFramebufferForMultiPassEffect(glm::uvec2 minRequiredSize) { diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.h b/aui.views/src/AUI/GL/OpenGLRenderer.h index 33ef92cfd..0242566d1 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.h +++ b/aui.views/src/AUI/GL/OpenGLRenderer.h @@ -12,12 +12,15 @@ #pragma once +#include +#include #include "AUI/GL/Program.h" #include "AUI/GL/Framebuffer.h" #include "AUI/GL/Vao.h" #include "AUI/Render/ABorderStyle.h" #include "AUI/GL/RenderTarget/TextureRenderTarget.h" #include "IBatchingRenderer.h" +#include "glm/fwd.hpp" class OpenGLRenderer final: public IBatchingRenderer { friend class OpenGLPrerenderedString; @@ -65,6 +68,11 @@ friend class OpenGLMultiStringCanvas; AOptional mSymbolShaderSubPixel; AOptional mSquareSectorShader; AOptional mLineSolidDashedShader; + static inline constexpr size_t MAX_BATCH_ELEMENTS = 250; + static inline constexpr size_t BATCH_VERTEX_AMOUNT = MAX_BATCH_ELEMENTS * 4; + static const size_t mQuadVertexCount = 4; + std::array mBatchVerticies; + std::array::iterator mCurrentBatchVertex; gl::Vao mRectangleVao; gl::Vao mBorderVao; gl::Texture2D mGradientTexture; @@ -98,6 +106,7 @@ friend class OpenGLMultiStringCanvas; static std::array getVerticesForRect(glm::vec2 position, glm::vec2 size); + void appendBatchVerticiesForRect(const glm::vec2 position, const glm::vec2 size, const int zIndex); FontEntryData* getFontEntryData(const AFontStyle& fontStyle); @@ -126,17 +135,17 @@ friend class OpenGLMultiStringCanvas; */ FramebufferFromPool getFramebufferForMultiPassEffect(glm::uvec2 minRequiredSize); - void drawRectImpl(glm::vec2 position, glm::vec2 size); + void drawRectImpl(const glm::vec2 position, const glm::vec2 size, const int zIndex); private: // Helper methods that perform the actual rendering for each command. - void renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size); - void renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius); - void renderRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float lineWidth); - void renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, int borderWidth); - void renderBoxShadow(const Cmd& cmd, glm::vec2 position, glm::vec2 size, float blurRadius, const AColor& color); - void renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, glm::vec2 size, float blurRadius, float spreadRadius, float borderRadius, const AColor& color, glm::vec2 offset); + void renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const int zIndex); + void renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, const int zIndex); + void renderRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float lineWidth, const int zIndex); + void renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, int borderWidth, const int zIndex); + void renderBoxShadow(const Cmd& cmd, glm::vec2 position, glm::vec2 size, float blurRadius, const AColor& color, const int zIndex); + void renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, glm::vec2 size, float blurRadius, float spreadRadius, float borderRadius, const AColor& color, glm::vec2 offset, const int zIndex); void renderString(const Cmd& cmd, glm::vec2 position, const AString& string, const AFontStyle& fs); void renderLines(const Cmd& cmd, const ABrush& brush, AArrayView points, const ABorderStyle& style, AMetric width); void renderLines(const Cmd& cmd, const ABrush& brush, AArrayView> points, const ABorderStyle& style, AMetric width); diff --git a/aui.views/src/AUI/GL/Vao.cpp b/aui.views/src/AUI/GL/Vao.cpp index 553d95413..e3cb786cc 100644 --- a/aui.views/src/AUI/GL/Vao.cpp +++ b/aui.views/src/AUI/GL/Vao.cpp @@ -64,6 +64,7 @@ void gl::Vao::insertIfKeyMismatches( goAhead: insert(index, data, dataSize, vertexSize, dataType, key); } + void gl::Vao::insert( GLuint index, const char* data, GLsizeiptr dataSize, GLuint vertexSize, GLenum dataType, const char* key) { bind(); @@ -134,7 +135,7 @@ void gl::Vao::drawElements(GLenum type) { glDrawElements(type, mIndicesCount, mIndicesType, 0); } -void gl::Vao::indices(AArrayView data) { +void gl::Vao::indices(std::span data) { bind(); GLenum drawType = GL_DYNAMIC_DRAW; if (mIndicesBuffer == 0) { @@ -144,11 +145,11 @@ void gl::Vao::indices(AArrayView data) { } mIndicesCount = static_cast(data.size()); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndicesBuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.sizeInBytes(), data.data(), drawType); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.size_bytes(), data.data(), drawType); mIndicesType = GL_UNSIGNED_INT; } -void gl::Vao::indices(AArrayView data) { +void gl::Vao::indices(std::span data) { bind(); GLenum drawType = GL_DYNAMIC_DRAW; if (mIndicesBuffer == 0) { @@ -158,6 +159,6 @@ void gl::Vao::indices(AArrayView data) { } mIndicesCount = static_cast(data.size()); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndicesBuffer); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.sizeInBytes(), data.data(), drawType); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.size_bytes(), data.data(), drawType); mIndicesType = GL_UNSIGNED_SHORT; } diff --git a/aui.views/src/AUI/GL/Vao.h b/aui.views/src/AUI/GL/Vao.h index 38d0785b5..854b372a1 100644 --- a/aui.views/src/AUI/GL/Vao.h +++ b/aui.views/src/AUI/GL/Vao.h @@ -14,7 +14,6 @@ #include "AUI/GL/gl.h" #include #include "AUI/Common/AVector.h" -#include "AUI/Util/AArrayView.h" #include "AUI/Views.h" namespace gl { @@ -53,12 +52,12 @@ class API_AUI_VIEWS Vao { * @param data vertex data * @param key see gl::Vao::Buffer::lastModifierKey */ - template - void insert(GLuint index, AArrayView data, const char* key) { + template + void insert(GLuint index, std::span data, const char* key) { if constexpr (std::is_same_v) { - insertInteger(index, (const char*) data.data(), data.sizeInBytes(), 1, GL_UNSIGNED_INT); + insertInteger(index, (const char*) data.data(), data.size_bytes(), 1, GL_UNSIGNED_INT); } else { - insert(index, (const char*) data.data(), data.sizeInBytes(), sizeof(T) / sizeof(float), GL_FLOAT, key); + insert(index, (const char*) data.data(), data.size_bytes(), sizeof(T) / sizeof(float), GL_FLOAT, key); } } @@ -68,23 +67,23 @@ class API_AUI_VIEWS Vao { * @param data vertex data * @param key see gl::Vao::Buffer::lastModifierKey */ - template - void insertIfKeyMismatches(GLuint index, AArrayView data, const char* key) { + template + void insertIfKeyMismatches(GLuint index, std::span data, const char* key) { insertIfKeyMismatches( - index, (const char*) data.data(), data.sizeInBytes(), sizeof(T) / sizeof(float), GL_FLOAT, key); + index, (const char*) data.data(), data.size_bytes(), sizeof(T) / sizeof(float), GL_FLOAT, key); } /** * @brief Uploads VBO indices * @param data indices */ - void indices(AArrayView data); + void indices(std::span data); /** * @brief Uploads VBO indices * @param data indices */ - void indices(AArrayView data); + void indices(std::span data); void drawArrays(GLenum type, GLsizei count); From 27257a2c629a3b6dacebf537c386c9d0972f8350 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Sun, 15 Feb 2026 20:55:17 +0300 Subject: [PATCH 10/22] batching: fixed batch breaking --- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index 06fc19ca4..dc8771a1d 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -307,7 +307,7 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { continue; } // TODO: don't draw for non drawing commands like set window - breakBatch = breakBatch or (currentBatchId != nextId); + breakBatch = currentBatchId != nextId; if (not breakBatch) continue; From 7c945dd898ccac0b7684858a1ceaf7ab580f9009 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Mon, 23 Feb 2026 04:52:30 +0300 Subject: [PATCH 11/22] batching: zIndex support in vertes shader --- aui.views/shaders/basic.vsh | 8 ++- aui.views/shaders/basic_uv.vsh | 6 +- aui.views/src/AUI/GL/IBatchingRenderer.h | 2 - aui.views/src/AUI/GL/OpenGLRenderer.cpp | 84 +++++++++++++----------- aui.views/src/AUI/GL/OpenGLRenderer.h | 8 +-- aui.views/src/AUI/GL/Vao.cpp | 28 +++++++- aui.views/src/AUI/GL/Vao.h | 2 + 7 files changed, 86 insertions(+), 52 deletions(-) diff --git a/aui.views/shaders/basic.vsh b/aui.views/shaders/basic.vsh index f9bd046a5..a1e5a25be 100644 --- a/aui.views/shaders/basic.vsh +++ b/aui.views/shaders/basic.vsh @@ -1,10 +1,12 @@ input { - [0] vec2 pos + [0] vec3 pos } uniform { mat4 transform } entry { - sl_position = uniform.transform * vec4(input.pos, 0, 1) -} \ No newline at end of file + vec4 position = uniform.transform * vec4(input.pos, 1) + position.z = input.pos.z + sl_position = position +} diff --git a/aui.views/shaders/basic_uv.vsh b/aui.views/shaders/basic_uv.vsh index 2c6d7edc2..5a75f9a70 100644 --- a/aui.views/shaders/basic_uv.vsh +++ b/aui.views/shaders/basic_uv.vsh @@ -12,7 +12,9 @@ inter { } entry { - sl_position = uniform.transform * vec4(input.pos.xy, 0, 1) + vec4 position = uniform.transform * vec4(input.pos.xyz, 1) + position.z = input.pos.z inter.vertex = input.pos inter.uv = input.uv -} \ No newline at end of file + sl_position = position +} diff --git a/aui.views/src/AUI/GL/IBatchingRenderer.h b/aui.views/src/AUI/GL/IBatchingRenderer.h index 03821a957..472e78df1 100644 --- a/aui.views/src/AUI/GL/IBatchingRenderer.h +++ b/aui.views/src/AUI/GL/IBatchingRenderer.h @@ -107,7 +107,6 @@ class IBatchingRenderer : public IRenderer { CmdBoxShadowInner, CmdString, CmdLines, CmdPoints, CmdLinesPairs, CmdSquareSector, CmdNewRenderViewToTexture, CmdSetWindow>; Arg arg; - int zIndex; BatchId batchId; }; @@ -143,7 +142,6 @@ class IBatchingRenderer : public IRenderer { .transform = getTransform(), .color = getColor(), .arg = std::move(arg), - .zIndex = static_cast(mCmds.size()) }); } diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index dc8771a1d..b5cfc8b80 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -239,12 +239,10 @@ OpenGLRenderer::OpenGLRenderer() { aui::sl_gen::line_solid_dashed::fsh::glsl120::Shader>(mLineSolidDashedShader); { - GLuint INDICES[] = {0, 1, 2, 2, 1, 3}; - mRectangleVao.indices(std::span{INDICES}); + mRectangleVao.indicesByCount(BATCH_VERTEX_COUNT); } { - GLuint INDICES[] = {0, 1, 2, 3, 4, 5, 6, 7}; - mBorderVao.indices(std::span{INDICES}); + mRectangleVao.indicesByCount(BATCH_VERTEX_COUNT); } mBatchVerticies.fill(glm::vec3{0}); mCurrentBatchVertex = mBatchVerticies.begin(); @@ -284,7 +282,25 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { uint16_t currentBatchId; bool breakBatch = false; for (auto& cmd : cmds) { + u_int16_t nextId = cmd.batchId.value + 1; // + 1 so 0 ID cmd 0 ID brush != NULL + if (!currentBatchId) { + currentBatchId = nextId; + goto dispatching; + } + // TODO: don't draw for non drawing commands like set window + breakBatch = currentBatchId != nextId; + if (not breakBatch) + goto dispatching; + + mRectangleVao.insert(0, std::span{mBatchVerticies}, "Batch"); + mRectangleVao.drawElements(); + currentBatchId = nextId; + + std::ranges::fill(mBatchVerticies, glm::vec3(0)); + mCurrentBatchVertex = mBatchVerticies.begin(); // TODO: add logic here so the batch breaks if BATCH_VERTEX_AMOUNT will be exceeded + +dispatching: std::visit(aui::lambda_overloaded{ [&](const CmdRectangle& c) { renderRectangle(cmd, c.brush, c.position, c.size, c.zIndex); }, [&](const CmdRoundedRectangle& c) { renderRoundedRectangle(cmd, c.brush, c.position, c.size, c.radius, c.zIndex); }, @@ -292,7 +308,7 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { [&](const CmdRoundedRectangleBorder& c) { renderRoundedRectangleBorder(cmd, c.brush, c.position, c.size, c.radius, c.borderWidth, c.zIndex); }, [&](const CmdBoxShadow& c) { renderBoxShadow(cmd, c.position, c.size, c.blurRadius, c.color, c.zIndex); }, [&](const CmdBoxShadowInner& c) { renderBoxShadowInner(cmd, c.position, c.size, c.blurRadius, c.spreadRadius, c.borderRadius, c.color, c.offset, c.zIndex); }, - [&](const CmdString& c) { renderString(cmd, c.position, c.string, c.fs); }, + [&](const CmdString& c) { /* renderString(cmd, c.position, c.string, c.fs); */ }, [&](const CmdLines& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, [&](const CmdPoints& c) { renderPoints(cmd, c.brush, c.points, c.size); }, [&](const CmdLinesPairs& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, @@ -300,23 +316,6 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { [&](const CmdSetWindow& c) { mWindow = c.window; }, [&](const CmdNewRenderViewToTexture&){ /* handled elsewhere */ } }, cmd.arg); - - u_int16_t nextId = cmd.batchId.value + 1; // + 1 so 0 ID cmd 0 ID brush != NULL - if (!currentBatchId) { - currentBatchId = nextId; - continue; - } - // TODO: don't draw for non drawing commands like set window - breakBatch = currentBatchId != nextId; - if (not breakBatch) - continue; - - mRectangleVao.insert(0, std::span{mBatchVerticies}, "Batch"); - mRectangleVao.drawElements(); - currentBatchId = nextId; - - std::ranges::fill(mBatchVerticies, glm::vec3(0)); - mCurrentBatchVertex = mBatchVerticies.begin(); } } @@ -342,10 +341,12 @@ std::array OpenGLRenderer::getVerticesForRect(glm::vec2 position, }; } +static constexpr size_t Z_DEPTH = 1000; void OpenGLRenderer::appendBatchVerticiesForRect(const glm::vec2 position, const glm::vec2 size, const int zIndex) { float x = position.x; float y = position.y; - float z = zIndex; + // TODO: remove this for release, transform in shader instead + float z = 1 - 2 * zIndex * (1. / Z_DEPTH); float w = x + size.x; float h = y + size.y; @@ -363,10 +364,10 @@ void OpenGLRenderer::appendBatchVerticiesForRect(const glm::vec2 position, const void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const int zIndex) { std::visit(aui::lambda_overloaded{ [&](const ALinearGradientBrush& brush) { - gradientBrush(cmd, brush, *this, *mGradientShader); + // gradientBrush(cmd, brush, *this, *mGradientShader); }, [&](const ATexturedBrush& brush) { - texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); + // texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); }, [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *this, *mSolidShader); @@ -505,14 +506,15 @@ void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, w += blurRadius; h += blurRadius; - const glm::vec2 uvs[] = { - {x, h}, - {w, h}, - {x, y}, - {w, y}, - }; + // const glm::vec2 uvs[] = { + // {x, h}, + // {w, h}, + // {x, y}, + // {w, y}, + // }; - mRectangleVao.insert(0, std::span{uvs}, "boxShadowInner"); + // mRectangleVao.insert(0, std::span{uvs}, "boxShadowInner"); + // drawRectImpl(glm::vec2{x, y}, glm::vec2{w, h}, zIndex); } void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, @@ -542,14 +544,15 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, float w = x + size.x; float h = y + size.y; - const glm::vec2 uvs[] = { - {x, h}, - {w, h}, - {x, y}, - {w, y}, - }; + // const glm::vec2 uvs[] = { + // {x, h}, + // {w, h}, + // {x, y}, + // {w, y}, + // }; - mRectangleVao.insert(0, std::span{uvs}, "boxShadowInner"); + // mRectangleVao.insert(0, std::span{uvs}, "boxShadowInner"); + drawRectImpl(glm::vec2{x, y}, glm::vec2{w, h}, zIndex); } void OpenGLRenderer::renderString(const Cmd& cmd, glm::vec2 position, @@ -1106,9 +1109,10 @@ void OpenGLRenderer::beginPaint(glm::uvec2 windowSize) { gl::State::useProgram(0); - glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glClearColor(0, 0, 0, 0); + glEnable(GL_DEPTH_TEST); + glDepthFunc(GL_LESS); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); setBlending(Blending::NORMAL); diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.h b/aui.views/src/AUI/GL/OpenGLRenderer.h index 0242566d1..786853928 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.h +++ b/aui.views/src/AUI/GL/OpenGLRenderer.h @@ -68,11 +68,11 @@ friend class OpenGLMultiStringCanvas; AOptional mSymbolShaderSubPixel; AOptional mSquareSectorShader; AOptional mLineSolidDashedShader; - static inline constexpr size_t MAX_BATCH_ELEMENTS = 250; - static inline constexpr size_t BATCH_VERTEX_AMOUNT = MAX_BATCH_ELEMENTS * 4; + static constexpr size_t MAX_BATCH_ELEMENTS = 10000; + static constexpr size_t BATCH_VERTEX_COUNT = MAX_BATCH_ELEMENTS * 4; static const size_t mQuadVertexCount = 4; - std::array mBatchVerticies; - std::array::iterator mCurrentBatchVertex; + std::array mBatchVerticies; + std::array::iterator mCurrentBatchVertex; gl::Vao mRectangleVao; gl::Vao mBorderVao; gl::Texture2D mGradientTexture; diff --git a/aui.views/src/AUI/GL/Vao.cpp b/aui.views/src/AUI/GL/Vao.cpp index e3cb786cc..9fce95464 100644 --- a/aui.views/src/AUI/GL/Vao.cpp +++ b/aui.views/src/AUI/GL/Vao.cpp @@ -22,6 +22,8 @@ #include "Vao.h" #include +#include "AUI/GL/gl.h" +#include "AUI/Util/Assert.h" #include "State.h" gl::Vao::Vao() { @@ -149,7 +151,29 @@ void gl::Vao::indices(std::span data) { mIndicesType = GL_UNSIGNED_INT; } -void gl::Vao::indices(std::span data) { +static std::vector generateQuadIndices(const size_t vertexCount) { + AUI_ASSERT(vertexCount % 4 == 0); + + const size_t quadCount = vertexCount / 4; + std::vector indices; + indices.reserve(quadCount * 6); + + for (size_t quad = 0; quad < quadCount; ++quad) { + const unsigned short baseVertex = static_cast(quad * 4); + + indices.push_back(baseVertex + 0); + indices.push_back(baseVertex + 1); + indices.push_back(baseVertex + 2); + + indices.push_back(baseVertex + 2); + indices.push_back(baseVertex + 1); + indices.push_back(baseVertex + 3); + } + + return indices; +} + +void gl::Vao::indicesByCount(const size_t vertexCount) { bind(); GLenum drawType = GL_DYNAMIC_DRAW; if (mIndicesBuffer == 0) { @@ -157,6 +181,8 @@ void gl::Vao::indices(std::span data) { assert(mIndicesBuffer); drawType = GL_STATIC_DRAW; } + auto indices = std::move(generateQuadIndices(vertexCount)); + auto data = std::span{indices}; mIndicesCount = static_cast(data.size()); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndicesBuffer); glBufferData(GL_ELEMENT_ARRAY_BUFFER, data.size_bytes(), data.data(), drawType); diff --git a/aui.views/src/AUI/GL/Vao.h b/aui.views/src/AUI/GL/Vao.h index 854b372a1..1e33ea054 100644 --- a/aui.views/src/AUI/GL/Vao.h +++ b/aui.views/src/AUI/GL/Vao.h @@ -85,6 +85,8 @@ class API_AUI_VIEWS Vao { */ void indices(std::span data); + void indicesByCount(const size_t vertexCount); + void drawArrays(GLenum type, GLsizei count); /** From f9c24d6b19b808fba93b094cd78d78245958bfd2 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Mon, 23 Feb 2026 15:56:01 +0300 Subject: [PATCH 12/22] batching: moved vertex transformation to CPU --- aui.views/shaders/basic.vsh | 7 +-- aui.views/shaders/basic_uv.vsh | 8 +--- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 48 +++++++++---------- aui.views/src/AUI/GL/OpenGLRenderer.h | 5 +- aui.views/src/AUI/View/AView.cpp | 12 +++-- aui.views/src/AUI/View/AView.h | 1 + aui.views/src/AUI/View/AViewContainerBase.cpp | 3 +- examples/ui/game_inventory/src/main.cpp | 10 ++-- 8 files changed, 43 insertions(+), 51 deletions(-) diff --git a/aui.views/shaders/basic.vsh b/aui.views/shaders/basic.vsh index a1e5a25be..1c5e00cde 100644 --- a/aui.views/shaders/basic.vsh +++ b/aui.views/shaders/basic.vsh @@ -1,12 +1,7 @@ input { [0] vec3 pos } -uniform { - mat4 transform -} entry { - vec4 position = uniform.transform * vec4(input.pos, 1) - position.z = input.pos.z - sl_position = position + sl_position = vec4(input.pos, 1) } diff --git a/aui.views/shaders/basic_uv.vsh b/aui.views/shaders/basic_uv.vsh index 5a75f9a70..ec1200858 100644 --- a/aui.views/shaders/basic_uv.vsh +++ b/aui.views/shaders/basic_uv.vsh @@ -1,7 +1,3 @@ -uniform { - mat4 transform -} - input { [0] vec4 pos [1] vec2 uv @@ -12,9 +8,7 @@ inter { } entry { - vec4 position = uniform.transform * vec4(input.pos.xyz, 1) - position.z = input.pos.z + sl_position = vec4(input.pos.xyz, 1) inter.vertex = input.pos inter.uv = input.uv - sl_position = position } diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index b5cfc8b80..74b7b5808 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -342,13 +342,12 @@ std::array OpenGLRenderer::getVerticesForRect(glm::vec2 position, } static constexpr size_t Z_DEPTH = 1000; -void OpenGLRenderer::appendBatchVerticiesForRect(const glm::vec2 position, const glm::vec2 size, const int zIndex) { +void OpenGLRenderer::appendBatchVerticiesForRect(const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform) { float x = position.x; float y = position.y; - // TODO: remove this for release, transform in shader instead - float z = 1 - 2 * zIndex * (1. / Z_DEPTH); float w = x + size.x; float h = y + size.y; + float z = -1.f + zIndex * (1. / Z_DEPTH); std::array verticies { glm::vec3 { x, h, z }, @@ -357,8 +356,10 @@ void OpenGLRenderer::appendBatchVerticiesForRect(const glm::vec2 position, const glm::vec3 { w, y, z }, }; - std::ranges::copy(verticies, mCurrentBatchVertex); - mCurrentBatchVertex += mQuadVertexCount; + for (const auto& vertex : verticies) { + glm::vec4 vertexTransformed = transform * glm::vec4(vertex, 1.0f); + *mCurrentBatchVertex++ = glm::vec3(vertexTransformed); + } } void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const int zIndex) { @@ -374,15 +375,14 @@ void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::v }, [](const ACustomShaderBrush& ) {}, }, brush); - gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, cmd.transform); - drawRectImpl(position, size, zIndex); + drawRectImpl(position, size, zIndex, cmd.transform); } -void OpenGLRenderer::drawRectImpl(const glm::vec2 position, const glm::vec2 size, const int zIndex) { +void OpenGLRenderer::drawRectImpl(const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform) { mRectangleVao.bind(); - appendBatchVerticiesForRect(position, size, zIndex); + appendBatchVerticiesForRect(position, size, zIndex, transform); } void OpenGLRenderer::identityUv() { @@ -410,7 +410,7 @@ void OpenGLRenderer::renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, identityUv(); gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_SIZE, 2.f * radius / size); - drawRectImpl(position, size, zIndex); + drawRectImpl(position, size, zIndex, cmd.transform); } void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, @@ -425,7 +425,6 @@ void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *this, *mSolidShader); }, [](const ACustomShaderBrush& ) {}, }, brush); - gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, cmd.transform); identityUv(); //rect.insert(0, getVerticesForRect(x + 0.25f + lineWidth * 0.5f, y + 0.25f + lineWidth * 0.5f, width - (0.25f + lineWidth * 0.5f), height - (0.75f + lineWidth * 0.5f))); @@ -475,8 +474,7 @@ void OpenGLRenderer::renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_SIZE, 2.f * radius / size); gl::Program::currentShader()->set(aui::ShaderUniforms::INNER_SIZE, 2.f * (radius - borderWidth) / innerSize); gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_TO_INNER, size / innerSize); - gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, cmd.transform); - drawRectImpl(position, size, zIndex); + drawRectImpl(position, size, zIndex, cmd.transform); } void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, @@ -491,7 +489,6 @@ void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, mBoxShadowShader->set(aui::ShaderUniforms::SL_UNIFORM_SIGMA, blurRadius / 2.f); mBoxShadowShader->set(aui::ShaderUniforms::SL_UNIFORM_LOWER, position + size); mBoxShadowShader->set(aui::ShaderUniforms::SL_UNIFORM_UPPER, position); - mBoxShadowShader->set(aui::ShaderUniforms::SL_UNIFORM_TRANSFORM, cmd.transform); mBoxShadowShader->set(aui::ShaderUniforms::COLOR, cmd.color * color); mRectangleVao.bind(); @@ -532,7 +529,6 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, mBoxShadowInnerShader->set(aui::ShaderUniforms::SL_UNIFORM_SIGMA, blurRadius / 2.f); mBoxShadowInnerShader->set(aui::ShaderUniforms::SL_UNIFORM_LOWER, position + offset + size - spreadRadius); mBoxShadowInnerShader->set(aui::ShaderUniforms::SL_UNIFORM_UPPER, position + offset + spreadRadius); - mBoxShadowInnerShader->set(aui::ShaderUniforms::SL_UNIFORM_TRANSFORM, cmd.transform); mBoxShadowInnerShader->set(aui::ShaderUniforms::COLOR, cmd.color * color); gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_SIZE, 2.f * borderRadius / size); @@ -552,7 +548,7 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, // }; // mRectangleVao.insert(0, std::span{uvs}, "boxShadowInner"); - drawRectImpl(glm::vec2{x, y}, glm::vec2{w, h}, zIndex); + drawRectImpl(glm::vec2{x, y}, glm::vec2{w, h}, zIndex, cmd.transform); } void OpenGLRenderer::renderString(const Cmd& cmd, glm::vec2 position, @@ -1047,7 +1043,7 @@ void OpenGLRenderer::renderPoints(const Cmd& cmd, const ABrush& brush, AArrayVie #if AUI_PLATFORM_ANDROID || AUI_PLATFORM_IOS || AUI_PLATFORM_EMSCRIPTEN // TODO slow, use instancing instead for (auto point : points) { - drawRectImpl(point - glm::vec2(widthPx / 2), glm::vec2(widthPx)); + drawRectImpl(point - glm::vec2(widthPx / 2), glm::vec2(widthPx), cmd.transform); } #else glPointSize(widthPx); @@ -1088,7 +1084,7 @@ void OpenGLRenderer::renderSquareSector(const Cmd& cmd, const ABrush& brush, gl::Program::currentShader()->set(aui::ShaderUniforms::M2, m2); // TODO: replace 0 with zIndex - drawRectImpl(position, size, 0); + drawRectImpl(position, size, 0, cmd.transform); } @@ -1487,8 +1483,8 @@ void main() { identityUv(); glDisable(GL_BLEND); - // TODO: replace 0 with zIndex - drawRectImpl({}, size, 0); + // TODO: replace 0 with zIndex and add transform, then uncomment + // drawRectImpl({}, size, 0); glEnable(GL_BLEND); areaOfInterest = AreaOfInterest { @@ -1582,8 +1578,8 @@ void main() {{ } gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, mTransform); identityUv(); - // TODO: Replace 0 with zIndex - drawRectImpl({}, sizeDownscaled, 0); + // TODO: replace 0 with zIndex and add transform, then uncomment + // drawRectImpl({}, sizeDownscaled, 0); areaOfInterest.reset(); // release borrowed framebuffer before requesting another one @@ -1607,8 +1603,8 @@ void main() {{ stepSize / 2.f); } gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, mTransform); - // TODO: replace 0 with zIndex - drawRectImpl({}, sizeDownscaled, 0); + // TODO: replace 0 with zIndex and add transform, then uncomment + // drawRectImpl({}, sizeDownscaled, 0); areaOfInterest = AreaOfInterest { .framebuffer = std::move(offscreen2), @@ -1642,8 +1638,8 @@ void main() {{ texture.setupLinear(); gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, mTransform); - // TODO: replace 0 with zIndex - drawRectImpl(position, size, 0); + // TODO: replace 0 with zIndex and add transform, then uncomment + // drawRectImpl(position, size, 0); } OpenGLRenderer::FramebufferFromPool OpenGLRenderer::getFramebufferForMultiPassEffect(glm::uvec2 minRequiredSize) { diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.h b/aui.views/src/AUI/GL/OpenGLRenderer.h index 786853928..bdbf9c367 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.h +++ b/aui.views/src/AUI/GL/OpenGLRenderer.h @@ -70,7 +70,6 @@ friend class OpenGLMultiStringCanvas; AOptional mLineSolidDashedShader; static constexpr size_t MAX_BATCH_ELEMENTS = 10000; static constexpr size_t BATCH_VERTEX_COUNT = MAX_BATCH_ELEMENTS * 4; - static const size_t mQuadVertexCount = 4; std::array mBatchVerticies; std::array::iterator mCurrentBatchVertex; gl::Vao mRectangleVao; @@ -106,7 +105,7 @@ friend class OpenGLMultiStringCanvas; static std::array getVerticesForRect(glm::vec2 position, glm::vec2 size); - void appendBatchVerticiesForRect(const glm::vec2 position, const glm::vec2 size, const int zIndex); + void appendBatchVerticiesForRect(const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform); FontEntryData* getFontEntryData(const AFontStyle& fontStyle); @@ -135,7 +134,7 @@ friend class OpenGLMultiStringCanvas; */ FramebufferFromPool getFramebufferForMultiPassEffect(glm::uvec2 minRequiredSize); - void drawRectImpl(const glm::vec2 position, const glm::vec2 size, const int zIndex); + void drawRectImpl(const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform); private: diff --git a/aui.views/src/AUI/View/AView.cpp b/aui.views/src/AUI/View/AView.cpp index ea3840054..1c391ef52 100644 --- a/aui.views/src/AUI/View/AView.cpp +++ b/aui.views/src/AUI/View/AView.cpp @@ -108,9 +108,10 @@ void AView::drawStencilMask(ARenderContext ctx) {getWidth() - mPadding.horizontal(), getHeight() - mPadding.vertical()}, glm::max(mBorderRadius - std::min(mPadding.horizontal(), mPadding.vertical()), 0.f)); } else { - ctx.render.rectangle(ASolidBrush{}, - {mPadding.left, mPadding.top}, - {getWidth() - mPadding.horizontal(), getHeight() - mPadding.vertical()}); + // TODO: figure out why this is rendered opaque when batching + // ctx.render.rectangle(ASolidBrush{}, + // {mPadding.left, mPadding.top}, + // {getWidth() - mPadding.horizontal(), getHeight() - mPadding.vertical()}); } break; @@ -290,6 +291,11 @@ void AView::getTransform(glm::mat4& transform) const transform = glm::translate(transform, glm::vec3{ getPosition(), 0.f }); } +const glm::mat4 AView::getTransformCopy(glm::mat4 transform) const +{ + return glm::translate(transform, glm::vec3{ getPosition(), 0.f }); +} + void AView::pack() { setSize({ getMinimumWidth(), getMinimumHeight() }); diff --git a/aui.views/src/AUI/View/AView.h b/aui.views/src/AUI/View/AView.h index ba697bb86..b2cf5a239 100644 --- a/aui.views/src/AUI/View/AView.h +++ b/aui.views/src/AUI/View/AView.h @@ -562,6 +562,7 @@ class API_AUI_VIEWS AView: public AObject void setAnimator(const _& animator); void getTransform(glm::mat4& transform) const; + const glm::mat4 getTransformCopy(glm::mat4 transform = glm::mat4{1.}) const; [[nodiscard]] int getExpandingHorizontal() const diff --git a/aui.views/src/AUI/View/AViewContainerBase.cpp b/aui.views/src/AUI/View/AViewContainerBase.cpp index 138753067..bd1c82539 100644 --- a/aui.views/src/AUI/View/AViewContainerBase.cpp +++ b/aui.views/src/AUI/View/AViewContainerBase.cpp @@ -83,7 +83,8 @@ void AViewContainerBase::drawView(const _& view, ARenderContext contextOf glm::mat4 t(1.f); view->getTransform(t); contextOfTheView.render.setTransform(t); - contextOfTheView.render.setColor(AColor(1, 1, 1, view->getOpacity())); + // TODO: this is incomatible with batching, move to vertex + // contextOfTheView.render.setColor(AColor(1, 1, 1, view->getOpacity())); if (view->mRenderToTexture) [[unlikely]] { // view was prerendered to texture; see AView::markPixelDataInvalid view->mRenderToTexture->skipRedrawUntilTextureIsPresented = false; // Check invalidArea is not dirty; otherwise we would have to draw the views without render-to-texture diff --git a/examples/ui/game_inventory/src/main.cpp b/examples/ui/game_inventory/src/main.cpp index 1cf837573..595c8d092 100644 --- a/examples/ui/game_inventory/src/main.cpp +++ b/examples/ui/game_inventory/src/main.cpp @@ -58,11 +58,11 @@ _ itemStackView(const _>>& itemStack) { }, Vertical::Expanding { SpacerExpanding {}, - Label { AUI_REACT("{}"_format((*itemStack)->valueOr(ItemStack{}).count)) } AUI_OVERRIDE_STYLE { - ATextAlign::RIGHT, - TextColor { AColor::WHITE }, - TextShadow { AColor::BLACK, 1_dp, 1_dp }, - }, + // Label { AUI_REACT("{}"_format((*itemStack)->valueOr(ItemStack{}).count)) } AUI_OVERRIDE_STYLE { + // ATextAlign::RIGHT, + // TextColor { AColor::WHITE }, + // TextShadow { AColor::BLACK, 1_dp, 1_dp }, + // }, }, } AUI_OVERRIDE_STYLE { FixedSize { 32_dp }, From 0c7ac9dc3b394fa460e6213adaf42260a3e176eb Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Mon, 23 Feb 2026 16:44:56 +0300 Subject: [PATCH 13/22] batching: micro adjustments --- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 3 ++- aui.views/src/AUI/GL/OpenGLRenderer.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index 74b7b5808..c45c94c49 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -342,7 +342,8 @@ std::array OpenGLRenderer::getVerticesForRect(glm::vec2 position, } static constexpr size_t Z_DEPTH = 1000; -void OpenGLRenderer::appendBatchVerticiesForRect(const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform) { +void OpenGLRenderer::appendBatchVerticiesForRect( + const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform) { float x = position.x; float y = position.y; float w = x + size.x; diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.h b/aui.views/src/AUI/GL/OpenGLRenderer.h index bdbf9c367..731c7bd53 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.h +++ b/aui.views/src/AUI/GL/OpenGLRenderer.h @@ -68,7 +68,7 @@ friend class OpenGLMultiStringCanvas; AOptional mSymbolShaderSubPixel; AOptional mSquareSectorShader; AOptional mLineSolidDashedShader; - static constexpr size_t MAX_BATCH_ELEMENTS = 10000; + static constexpr size_t MAX_BATCH_ELEMENTS = 1000; static constexpr size_t BATCH_VERTEX_COUNT = MAX_BATCH_ELEMENTS * 4; std::array mBatchVerticies; std::array::iterator mCurrentBatchVertex; From b8d4b9cfa2e06de25da2d8ef8f56d51e64c01c19 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Sat, 28 Feb 2026 22:26:58 +0300 Subject: [PATCH 14/22] batching: fixed last batch handling --- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 80 +++++++++++++++---------- examples/ui/game_inventory/src/main.cpp | 2 +- 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index c45c94c49..6de8d1f2d 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include "OpenGLRenderer.h" @@ -248,27 +249,26 @@ OpenGLRenderer::OpenGLRenderer() { mCurrentBatchVertex = mBatchVerticies.begin(); } -static unsigned char getBrushIndex(const IBatchingRenderer::Cmd& cmd) { - unsigned char result = 1; - const char offset = 3; - - std::visit(aui::lambda_overloaded { - [&](const IBatchingRenderer::CmdRectangle& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdRoundedRectangle& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdRectangleBorder& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdRoundedRectangleBorder& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdLines& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdPoints& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdLinesPairs& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdSquareSector& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdSetWindow& arg) { result = offset - 1; }, - [&](const auto& arg) { }, - }, cmd.arg); - - return result; -} - void OpenGLRenderer::handleCmds(std::vector cmds) { + auto getBrushIndex = [](Cmd& cmd) { + unsigned char result = 1; + const char offset = 3; + + std::visit(aui::lambda_overloaded { + [&](const IBatchingRenderer::CmdRectangle& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdRoundedRectangle& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdRectangleBorder& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdRoundedRectangleBorder& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdLines& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdPoints& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdLinesPairs& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdSquareSector& arg) { result = arg.brush.index() + offset; }, + [&](const IBatchingRenderer::CmdSetWindow& arg) { result = offset - 1; }, + [&](const auto& arg) { }, + }, cmd.arg); + + return result; + }; for (auto& cmd : cmds) { cmd.batchId = { .cmdId = static_cast(cmd.arg.index()), @@ -279,28 +279,40 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { return cmdA.batchId.value > cmdB.batchId.value; }); - uint16_t currentBatchId; + auto &rectangleVao = mRectangleVao; + auto &batchVerticies = mBatchVerticies; + auto drawBatch = [&]() { + rectangleVao.insert(0, std::span{batchVerticies}, "Batch"); + rectangleVao.drawElements(); + }; + + uint16_t currentBatchId = 0; bool breakBatch = false; - for (auto& cmd : cmds) { + auto ¤tBatchVertex = mCurrentBatchVertex; + auto dispatch = [&](Cmd& cmd) { u_int16_t nextId = cmd.batchId.value + 1; // + 1 so 0 ID cmd 0 ID brush != NULL if (!currentBatchId) { currentBatchId = nextId; - goto dispatching; + return; } // TODO: don't draw for non drawing commands like set window - breakBatch = currentBatchId != nextId; - if (not breakBatch) - goto dispatching; + if (currentBatchId != nextId) { + breakBatch = true; + } + // TODO: add logic here so the batch breaks if BATCH_VERTEX_AMOUNT will be exceeded - mRectangleVao.insert(0, std::span{mBatchVerticies}, "Batch"); - mRectangleVao.drawElements(); + if (not breakBatch) + return; + drawBatch(); currentBatchId = nextId; + std::ranges::fill(batchVerticies, glm::vec3(0)); + currentBatchVertex = batchVerticies.begin(); + breakBatch = false; + }; - std::ranges::fill(mBatchVerticies, glm::vec3(0)); - mCurrentBatchVertex = mBatchVerticies.begin(); - // TODO: add logic here so the batch breaks if BATCH_VERTEX_AMOUNT will be exceeded + for (auto& cmd : cmds) { + dispatch(cmd); -dispatching: std::visit(aui::lambda_overloaded{ [&](const CmdRectangle& c) { renderRectangle(cmd, c.brush, c.position, c.size, c.zIndex); }, [&](const CmdRoundedRectangle& c) { renderRoundedRectangle(cmd, c.brush, c.position, c.size, c.radius, c.zIndex); }, @@ -308,7 +320,7 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { [&](const CmdRoundedRectangleBorder& c) { renderRoundedRectangleBorder(cmd, c.brush, c.position, c.size, c.radius, c.borderWidth, c.zIndex); }, [&](const CmdBoxShadow& c) { renderBoxShadow(cmd, c.position, c.size, c.blurRadius, c.color, c.zIndex); }, [&](const CmdBoxShadowInner& c) { renderBoxShadowInner(cmd, c.position, c.size, c.blurRadius, c.spreadRadius, c.borderRadius, c.color, c.offset, c.zIndex); }, - [&](const CmdString& c) { /* renderString(cmd, c.position, c.string, c.fs); */ }, + [&](const CmdString& c) { renderString(cmd, c.position, c.string, c.fs); }, [&](const CmdLines& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, [&](const CmdPoints& c) { renderPoints(cmd, c.brush, c.points, c.size); }, [&](const CmdLinesPairs& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, @@ -317,6 +329,8 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { [&](const CmdNewRenderViewToTexture&){ /* handled elsewhere */ } }, cmd.arg); } + if (mCurrentBatchVertex != mBatchVerticies.begin()) + drawBatch(); } diff --git a/examples/ui/game_inventory/src/main.cpp b/examples/ui/game_inventory/src/main.cpp index 595c8d092..6c0935eaa 100644 --- a/examples/ui/game_inventory/src/main.cpp +++ b/examples/ui/game_inventory/src/main.cpp @@ -112,7 +112,7 @@ AUI_ENTRY { auto state = _new(); state->items = - ranges::view::iota(0, 128) | ranges::view::transform([&](int i) { + ranges::views::iota(0, 256) | ranges::views::transform([&](int i) { return aui::ptr::manage_shared(new State::Cell { .contents = i <= 11 ? AOptional({ From b897a4fdd966d9b2243c3805021288ecb8963e63 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Sun, 1 Mar 2026 00:12:05 +0300 Subject: [PATCH 15/22] batching: minor improvements --- aui.views/src/AUI/GL/IBatchingRenderer.h | 4 +- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 47 +++++++++++++++--------- examples/ui/game_inventory/src/main.cpp | 5 +-- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/aui.views/src/AUI/GL/IBatchingRenderer.h b/aui.views/src/AUI/GL/IBatchingRenderer.h index 472e78df1..d9620025c 100644 --- a/aui.views/src/AUI/GL/IBatchingRenderer.h +++ b/aui.views/src/AUI/GL/IBatchingRenderer.h @@ -92,12 +92,14 @@ class IBatchingRenderer : public IRenderer { struct CmdSetWindow { AWindowBase* window; }; + using BatchId_t = uint16_t; union BatchId { struct { unsigned char cmdId : 8; unsigned char brushId : 8; + // uint16_t zIndex : 16; }; - uint16_t value; + BatchId_t value; }; struct Cmd { glm::mat4 transform; diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index 6de8d1f2d..483f94ef1 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -251,46 +251,57 @@ OpenGLRenderer::OpenGLRenderer() { void OpenGLRenderer::handleCmds(std::vector cmds) { auto getBrushIndex = [](Cmd& cmd) { - unsigned char result = 1; - const char offset = 3; + unsigned char result; + const char OFFSET = 3; std::visit(aui::lambda_overloaded { - [&](const IBatchingRenderer::CmdRectangle& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdRoundedRectangle& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdRectangleBorder& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdRoundedRectangleBorder& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdLines& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdPoints& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdLinesPairs& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdSquareSector& arg) { result = arg.brush.index() + offset; }, - [&](const IBatchingRenderer::CmdSetWindow& arg) { result = offset - 1; }, - [&](const auto& arg) { }, + [&](const auto& arg) { + if constexpr (requires { arg.brush; }) { + result = arg.brush.index() + OFFSET; + } else { + result = OFFSET - 1; + } + } }, cmd.arg); return result; }; + // TODO: Look into using z index as a batch key component to reduce overdraw + auto getZIndex = [](Cmd& cmd) -> uint16_t { + std::optional result; + + std::visit(aui::lambda_overloaded { + [&](const auto& arg) { + if constexpr (requires { arg.zIndex; }) { + result = arg.zIndex; + } + } + }, cmd.arg); + + return static_cast(result.value_or(999)); + }; for (auto& cmd : cmds) { cmd.batchId = { .cmdId = static_cast(cmd.arg.index()), - .brushId = getBrushIndex(cmd) + .brushId = getBrushIndex(cmd), }; } std::ranges::sort(cmds, [](const Cmd& cmdA, const Cmd& cmdB) { - return cmdA.batchId.value > cmdB.batchId.value; + return cmdA.batchId.value < cmdB.batchId.value; }); auto &rectangleVao = mRectangleVao; auto &batchVerticies = mBatchVerticies; - auto drawBatch = [&]() { + auto drawBatch = [&](const char *name) { rectangleVao.insert(0, std::span{batchVerticies}, "Batch"); rectangleVao.drawElements(); }; - uint16_t currentBatchId = 0; + BatchId_t currentBatchId = 0; bool breakBatch = false; auto ¤tBatchVertex = mCurrentBatchVertex; auto dispatch = [&](Cmd& cmd) { - u_int16_t nextId = cmd.batchId.value + 1; // + 1 so 0 ID cmd 0 ID brush != NULL + BatchId_t nextId = cmd.batchId.value + 1; // + 1 so 0 ID cmd 0 ID brush != NULL if (!currentBatchId) { currentBatchId = nextId; return; @@ -303,7 +314,7 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { if (not breakBatch) return; - drawBatch(); + drawBatch("Batch"); currentBatchId = nextId; std::ranges::fill(batchVerticies, glm::vec3(0)); currentBatchVertex = batchVerticies.begin(); diff --git a/examples/ui/game_inventory/src/main.cpp b/examples/ui/game_inventory/src/main.cpp index 6c0935eaa..2c2c5c3ab 100644 --- a/examples/ui/game_inventory/src/main.cpp +++ b/examples/ui/game_inventory/src/main.cpp @@ -108,11 +108,11 @@ AUI_ENTRY { .flags = ARenderContextFlags::NO_VSYNC | ARenderContextFlags::NO_SMOOTH, }); - auto window = _new("Game inventory", 600_dp, 500_dp); + auto window = _new("Game inventory", 1920_dp, 900_dp); auto state = _new(); state->items = - ranges::views::iota(0, 256) | ranges::views::transform([&](int i) { + ranges::views::iota(0, 512) | ranges::views::transform([&](int i) { return aui::ptr::manage_shared(new State::Cell { .contents = i <= 11 ? AOptional({ @@ -130,7 +130,6 @@ AUI_ENTRY { inventoryGrid(state), } AUI_OVERRIDE_STYLE { Expanding {}, - MaxSize { 700_dp, {} }, }, } AUI_OVERRIDE_STYLE { Padding { {}, 64_dp } }); window->show(); From 62662e628a697959fa050fa29408335d73c41088 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Sun, 1 Mar 2026 01:26:16 +0300 Subject: [PATCH 16/22] batching: minor improvements --- aui.views/shaders/basic.vsh | 2 +- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aui.views/shaders/basic.vsh b/aui.views/shaders/basic.vsh index 1c5e00cde..80d1dcdd6 100644 --- a/aui.views/shaders/basic.vsh +++ b/aui.views/shaders/basic.vsh @@ -3,5 +3,5 @@ input { } entry { - sl_position = vec4(input.pos, 1) + sl_position = vec4(input.pos.xyz, 1) } diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index 483f94ef1..735d426e9 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -341,7 +341,7 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { }, cmd.arg); } if (mCurrentBatchVertex != mBatchVerticies.begin()) - drawBatch(); + drawBatch("Batch"); } From 0a6660d167c118ee88f8d987739a9ce447f8a989 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Mon, 2 Mar 2026 15:18:56 +0300 Subject: [PATCH 17/22] batching: shader porting WIP --- aui.views/shaders/basic.vert | 11 + aui.views/shaders/solid.frag | 10 + aui.views/shaders_legacy/basic.vsh | 7 + aui.views/shaders_legacy/basic_uv.vsh | 14 ++ aui.views/shaders_legacy/border_rounded.fsh | 22 ++ aui.views/shaders_legacy/dashed.sl | 8 + aui.views/shaders_legacy/gradient.sl | 11 + aui.views/shaders_legacy/gradient_textured.sl | 10 + .../shaders_legacy/line_solid_dashed.fsh | 17 ++ aui.views/shaders_legacy/rect_gradient.fsh | 17 ++ .../shaders_legacy/rect_gradient_rounded.fsh | 20 ++ aui.views/shaders_legacy/rect_solid.fsh | 11 + .../shaders_legacy/rect_solid_rounded.fsh | 19 ++ aui.views/shaders_legacy/rect_textured.fsh | 16 ++ aui.views/shaders_legacy/rect_unblend.fsh | 18 ++ aui.views/shaders_legacy/rounded.sl | 11 + aui.views/shaders_legacy/shadow.fsh | 33 +++ aui.views/shaders_legacy/shadow_inner.fsh | 39 ++++ aui.views/shaders_legacy/square_sector.fsh | 21 ++ aui.views/shaders_legacy/symbol.fsh | 17 ++ aui.views/shaders_legacy/symbol.vsh | 17 ++ aui.views/shaders_legacy/symbol_sub.fsh | 18 ++ aui.views/src/AUI/GL/OpenGLRenderer.cpp | 193 +++++++++++------- aui.views/src/AUI/GL/OpenGLRenderer.h | 7 +- aui.views/src/AUI/GL/Vao.cpp | 12 +- 25 files changed, 493 insertions(+), 86 deletions(-) create mode 100644 aui.views/shaders/basic.vert create mode 100644 aui.views/shaders/solid.frag create mode 100644 aui.views/shaders_legacy/basic.vsh create mode 100644 aui.views/shaders_legacy/basic_uv.vsh create mode 100644 aui.views/shaders_legacy/border_rounded.fsh create mode 100644 aui.views/shaders_legacy/dashed.sl create mode 100644 aui.views/shaders_legacy/gradient.sl create mode 100644 aui.views/shaders_legacy/gradient_textured.sl create mode 100644 aui.views/shaders_legacy/line_solid_dashed.fsh create mode 100644 aui.views/shaders_legacy/rect_gradient.fsh create mode 100644 aui.views/shaders_legacy/rect_gradient_rounded.fsh create mode 100644 aui.views/shaders_legacy/rect_solid.fsh create mode 100644 aui.views/shaders_legacy/rect_solid_rounded.fsh create mode 100644 aui.views/shaders_legacy/rect_textured.fsh create mode 100644 aui.views/shaders_legacy/rect_unblend.fsh create mode 100644 aui.views/shaders_legacy/rounded.sl create mode 100644 aui.views/shaders_legacy/shadow.fsh create mode 100644 aui.views/shaders_legacy/shadow_inner.fsh create mode 100644 aui.views/shaders_legacy/square_sector.fsh create mode 100644 aui.views/shaders_legacy/symbol.fsh create mode 100644 aui.views/shaders_legacy/symbol.vsh create mode 100644 aui.views/shaders_legacy/symbol_sub.fsh diff --git a/aui.views/shaders/basic.vert b/aui.views/shaders/basic.vert new file mode 100644 index 000000000..ce8a76f0e --- /dev/null +++ b/aui.views/shaders/basic.vert @@ -0,0 +1,11 @@ +#version 300 es + +precision highp float; + +layout(location = 0) in vec3 pos; +layout(location = 1) in vec4 color; +flat out vec4 vertexColor; + +void main() { + gl_Position = vec4(pos.xyz, 1); +} diff --git a/aui.views/shaders/solid.frag b/aui.views/shaders/solid.frag new file mode 100644 index 000000000..a90644509 --- /dev/null +++ b/aui.views/shaders/solid.frag @@ -0,0 +1,10 @@ +#version 300 es + +precision highp float; + +flat in vec4 vertexColor; +out vec4 fragColor; + +void main() { + fragColor = vertexColor; +} diff --git a/aui.views/shaders_legacy/basic.vsh b/aui.views/shaders_legacy/basic.vsh new file mode 100644 index 000000000..80d1dcdd6 --- /dev/null +++ b/aui.views/shaders_legacy/basic.vsh @@ -0,0 +1,7 @@ +input { + [0] vec3 pos +} + +entry { + sl_position = vec4(input.pos.xyz, 1) +} diff --git a/aui.views/shaders_legacy/basic_uv.vsh b/aui.views/shaders_legacy/basic_uv.vsh new file mode 100644 index 000000000..ec1200858 --- /dev/null +++ b/aui.views/shaders_legacy/basic_uv.vsh @@ -0,0 +1,14 @@ +input { + [0] vec4 pos + [1] vec2 uv +} +inter { + vec4 vertex + vec2 uv +} + +entry { + sl_position = vec4(input.pos.xyz, 1) + inter.vertex = input.pos + inter.uv = input.uv +} diff --git a/aui.views/shaders_legacy/border_rounded.fsh b/aui.views/shaders_legacy/border_rounded.fsh new file mode 100644 index 000000000..073aabcd1 --- /dev/null +++ b/aui.views/shaders_legacy/border_rounded.fsh @@ -0,0 +1,22 @@ +import rounded + +uniform { + vec4 color + vec2 innerSize + vec2 outerToInner + vec2 outerSize +} + +inter { + vec2 uv +} + +output { + [0] vec4 albedo +} + +entry { + vec2 absolute = abs(inter.uv * 2 - 1) + output.albedo = uniform.color * vec4(1, 1, 1, rounded(absolute, uniform.outerSize) - rounded(absolute * uniform.outerToInner, uniform.innerSize)) +#flag glsl120 if (gl_FragColor.a < 0.1) discard; +} diff --git a/aui.views/shaders_legacy/dashed.sl b/aui.views/shaders_legacy/dashed.sl new file mode 100644 index 000000000..6c4427126 --- /dev/null +++ b/aui.views/shaders_legacy/dashed.sl @@ -0,0 +1,8 @@ +uniform { + float divider + float threshold +} + +float dashed(float distance) { + return step(mod(distance, uniform.divider), uniform.threshold); +} \ No newline at end of file diff --git a/aui.views/shaders_legacy/gradient.sl b/aui.views/shaders_legacy/gradient.sl new file mode 100644 index 000000000..f0436fe59 --- /dev/null +++ b/aui.views/shaders_legacy/gradient.sl @@ -0,0 +1,11 @@ +uniform { + vec4 color1 + vec4 color2 + mat3 matUv +} + +vec4 gradient(vec2 uv) { + vec3 transformedUv = uniform.matUv * vec3(uv, 1) + vec4 c = mix(uniform.color1, uniform.color2, clamp(transformedUv.x, 0, 1)) + return c +} \ No newline at end of file diff --git a/aui.views/shaders_legacy/gradient_textured.sl b/aui.views/shaders_legacy/gradient_textured.sl new file mode 100644 index 000000000..a83ff06f4 --- /dev/null +++ b/aui.views/shaders_legacy/gradient_textured.sl @@ -0,0 +1,10 @@ +uniform { + 2D gradientMap + mat3 matUv +} + +vec4 gradient(vec2 uv) { + vec3 transformedUv = uniform.matUv * vec3(uv, 1) + vec4 c = uniform.gradientMap[vec2(transformedUv.x, transformedUv.x)] + return c +} \ No newline at end of file diff --git a/aui.views/shaders_legacy/line_solid_dashed.fsh b/aui.views/shaders_legacy/line_solid_dashed.fsh new file mode 100644 index 000000000..983862fb9 --- /dev/null +++ b/aui.views/shaders_legacy/line_solid_dashed.fsh @@ -0,0 +1,17 @@ +import dashed + +uniform { + vec4 color +} + +inter { + vec4 vertex +} + +output { + [0] vec4 albedo +} + +entry { + output.albedo = uniform.color * dashed(inter.vertex.z) +} \ No newline at end of file diff --git a/aui.views/shaders_legacy/rect_gradient.fsh b/aui.views/shaders_legacy/rect_gradient.fsh new file mode 100644 index 000000000..cbfaef451 --- /dev/null +++ b/aui.views/shaders_legacy/rect_gradient.fsh @@ -0,0 +1,17 @@ +import gradient + +inter { + vec2 uv +} + +uniform { + vec4 color +} + +output { + [0] vec4 albedo +} + +entry { + output.albedo = uniform.color * gradient(inter.uv) +} \ No newline at end of file diff --git a/aui.views/shaders_legacy/rect_gradient_rounded.fsh b/aui.views/shaders_legacy/rect_gradient_rounded.fsh new file mode 100644 index 000000000..e43949eeb --- /dev/null +++ b/aui.views/shaders_legacy/rect_gradient_rounded.fsh @@ -0,0 +1,20 @@ +import gradient +import rounded + +inter { + vec2 uv +} + +uniform { + vec4 color + vec2 outerSize +} + +output { + [0] vec4 albedo +} + +entry { + output.albedo = uniform.color * gradient(inter.uv) * vec4(1, 1, 1, rounded(abs(inter.uv * 2 - 1), uniform.outerSize)) +#flag glsl120 if (gl_FragColor.a < 0.1) discard; +} diff --git a/aui.views/shaders_legacy/rect_solid.fsh b/aui.views/shaders_legacy/rect_solid.fsh new file mode 100644 index 000000000..3f438cb6c --- /dev/null +++ b/aui.views/shaders_legacy/rect_solid.fsh @@ -0,0 +1,11 @@ +uniform { + vec4 color +} + +output { + [0] vec4 albedo +} + +entry { + output.albedo = uniform.color +} \ No newline at end of file diff --git a/aui.views/shaders_legacy/rect_solid_rounded.fsh b/aui.views/shaders_legacy/rect_solid_rounded.fsh new file mode 100644 index 000000000..fad9ca193 --- /dev/null +++ b/aui.views/shaders_legacy/rect_solid_rounded.fsh @@ -0,0 +1,19 @@ +import rounded + +uniform { + vec4 color + vec2 outerSize +} + +inter { + vec2 uv +} + +output { + [0] vec4 albedo +} + +entry { + output.albedo = uniform.color * vec4(1, 1, 1, rounded(abs(inter.uv * 2 - 1), uniform.outerSize)) +#flag glsl120 if (gl_FragColor.a < 0.1) discard; +} diff --git a/aui.views/shaders_legacy/rect_textured.fsh b/aui.views/shaders_legacy/rect_textured.fsh new file mode 100644 index 000000000..95d698ad2 --- /dev/null +++ b/aui.views/shaders_legacy/rect_textured.fsh @@ -0,0 +1,16 @@ +uniform { + vec4 color + 2D albedo +} + +inter { + vec2 uv +} + +output { + [0] vec4 albedo +} + +entry { + output.albedo = uniform.color * uniform.albedo[inter.uv] +} diff --git a/aui.views/shaders_legacy/rect_unblend.fsh b/aui.views/shaders_legacy/rect_unblend.fsh new file mode 100644 index 000000000..50bfc8002 --- /dev/null +++ b/aui.views/shaders_legacy/rect_unblend.fsh @@ -0,0 +1,18 @@ +uniform { + vec4 color + 2D albedo +} + +inter { + vec2 uv +} + +output { + [0] vec4 albedo +} + +entry { + vec4 unblend = uniform.albedo[inter.uv] + unblend.xyz = unblend.xyz / unblend.a + output.albedo = uniform.color * unblend +} diff --git a/aui.views/shaders_legacy/rounded.sl b/aui.views/shaders_legacy/rounded.sl new file mode 100644 index 000000000..6b73db4aa --- /dev/null +++ b/aui.views/shaders_legacy/rounded.sl @@ -0,0 +1,11 @@ +float rounded(vec2 absolute, vec2 size) { + vec2 circleCenter = 1.0 - size; + vec2 rectangleShape = step(absolute, circleCenter) + + vec2 circle = (absolute - circleCenter) / (size); + float circles = step(circle.x * circle.x + circle.y * circle.y, 1.0) + + vec2 rectCut = step(vec2(0), vec2(1.0) - absolute) + + return clamp(rectangleShape.x + rectangleShape.y + circles, 0, 1) * rectCut.x * rectCut.y +} diff --git a/aui.views/shaders_legacy/shadow.fsh b/aui.views/shaders_legacy/shadow.fsh new file mode 100644 index 000000000..8fcacd748 --- /dev/null +++ b/aui.views/shaders_legacy/shadow.fsh @@ -0,0 +1,33 @@ +uniform { + vec4 color + vec2 lower + vec2 upper + float sigma +} + +output { + [0] vec4 albedo +} + +inter { + vec4 vertex +} + +vec4 erf(vec4 x) { + vec4 s = sign(x) + vec4 a = abs(x) + x = 1.0 + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a + x = x * x + return s - s / (x * x) +} + + +entry { + vec4 result = uniform.color + + vec2 v = inter.vertex.xy + vec4 query = vec4(v - vec2(uniform.lower), v - vec2(uniform.upper)) + vec4 integral = 0.5 + 0.5 * erf(query * (sqrt(0.5) / uniform.sigma)) + result.a = result.a * clamp((integral.z - integral.x) * (integral.w - integral.y), 0.0, 1.0) + output.albedo = result +} \ No newline at end of file diff --git a/aui.views/shaders_legacy/shadow_inner.fsh b/aui.views/shaders_legacy/shadow_inner.fsh new file mode 100644 index 000000000..39ef9e7ed --- /dev/null +++ b/aui.views/shaders_legacy/shadow_inner.fsh @@ -0,0 +1,39 @@ +import rounded + +uniform { + vec4 color + vec2 lower + vec2 upper + float sigma + + vec2 outerSize +} + +output { + [0] vec4 albedo +} + +inter { + vec4 vertex + vec2 uv +} + +vec4 erf(vec4 x) { + vec4 s = sign(x) + vec4 a = abs(x) + x = 1.0 + (0.278393 + (0.230389 + 0.078108 * (a * a)) * a) * a + x = x * x + return s - s / (x * x) +} + + +entry { + vec4 result = uniform.color + + vec2 v = inter.vertex.xy + vec4 query = vec4(v - vec2(uniform.lower), v - vec2(uniform.upper)) + vec4 integral = 0.5 + 0.5 * erf(query * (sqrt(0.5) / uniform.sigma)) + result.a = result.a * (1 - clamp((integral.z - integral.x) * (integral.w - integral.y), 0.0, 1.0)) + result.a = result.a * rounded(abs(inter.uv * 2 - 1), uniform.outerSize) + output.albedo = result +} \ No newline at end of file diff --git a/aui.views/shaders_legacy/square_sector.fsh b/aui.views/shaders_legacy/square_sector.fsh new file mode 100644 index 000000000..05590dcf8 --- /dev/null +++ b/aui.views/shaders_legacy/square_sector.fsh @@ -0,0 +1,21 @@ +uniform { + mat3 m1 + mat3 m2 + float whichAlgo +} + +inter { + vec2 uv +} + +output { + [0] vec4 albedo +} + +entry { + float m1 = step((uniform.m1 * vec3(inter.uv, 1)).x, 0) + float m2 = step((uniform.m2 * vec3(inter.uv, 1)).x, 0) + output.albedo = vec4(1, 1, 1, mix(m1 * m2, m1 + m2, uniform.whichAlgo)) + + #flag glsl120 if (gl_FragColor.a < 0.1) discard; +} \ No newline at end of file diff --git a/aui.views/shaders_legacy/symbol.fsh b/aui.views/shaders_legacy/symbol.fsh new file mode 100644 index 000000000..2fe2c500e --- /dev/null +++ b/aui.views/shaders_legacy/symbol.fsh @@ -0,0 +1,17 @@ +uniform { + vec4 color + 2D albedo +} + +inter { + vec2 uv +} + +output { + [0] vec4 albedo +} + +entry { + vec4 s = uniform.albedo[inter.uv] + output.albedo = uniform.color * vec4(1, 1, 1, s.x) +} diff --git a/aui.views/shaders_legacy/symbol.vsh b/aui.views/shaders_legacy/symbol.vsh new file mode 100644 index 000000000..1c3b0a295 --- /dev/null +++ b/aui.views/shaders_legacy/symbol.vsh @@ -0,0 +1,17 @@ +uniform { + mat4 transform + float uvScale +} + +input { + [0] vec2 pos + [1] vec2 uv +} +inter { + vec2 uv +} + +entry { + sl_position = uniform.transform * vec4(input.pos, 0, 1) + inter.uv = input.uv * uniform.uvScale +} diff --git a/aui.views/shaders_legacy/symbol_sub.fsh b/aui.views/shaders_legacy/symbol_sub.fsh new file mode 100644 index 000000000..dfbf12beb --- /dev/null +++ b/aui.views/shaders_legacy/symbol_sub.fsh @@ -0,0 +1,18 @@ +uniform { + vec4 color + 2D albedo +} + +inter { + vec2 uv +} + +output { + [0] vec4 albedo +} + +entry { + vec4 s = uniform.albedo[inter.uv] + vec4 c = uniform.color + output.albedo = vec4(c.xyz * s.xyz * c.a, (s.x + s.y + s.z) / 3 * c.a) +} diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index 735d426e9..414edb099 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -29,6 +29,7 @@ #include "AUI/GL/Program.h" #include "AUI/GL/Texture2D.h" #include "AUI/GL/Vao.h" +#include "AUI/GL/gl.h" #include "AUI/Platform/AInput.h" #include "AUI/Platform/APlatform.h" #include "AUI/Render/ABorderStyle.h" @@ -71,6 +72,8 @@ #include #include #include +#include +#include #include static constexpr auto LOG_TAG = "OpenGLRenderer"; @@ -102,7 +105,6 @@ static constexpr auto UV_BIAS = 0.001f; namespace { void gradientBrush(const IBatchingRenderer::Cmd& cmd, const ALinearGradientBrush& brush, OpenGLRenderer& renderer, gl::Program& shader) { - shader.use(); shader.set(aui::ShaderUniforms::COLOR, cmd.color); aui::render::brush::gradient::Helper h(brush); @@ -126,7 +128,8 @@ void gradientBrush(const IBatchingRenderer::Cmd& cmd, const ALinearGradientBrush void solidBrush(const IBatchingRenderer::Cmd& cmd, const ASolidBrush& brush, OpenGLRenderer& renderer, gl::Program& shader) { shader.use(); - shader.set(aui::ShaderUniforms::COLOR, cmd.color * brush.solidColor); + ALogger::info("OpenGL") << "Brush color: " << cmd.color.toString(); + renderer.appendColor(cmd.color * brush.solidColor); } void texturedBrush(const IBatchingRenderer::Cmd& cmd, const ATexturedBrush& brush, OpenGLRenderer& renderer, gl::Program& shader, gl::Vao& tempVao) { @@ -187,6 +190,29 @@ inline void useAuislShader(AOptional& out) { Fragment::setup(out->handle()); out->compile(); } + +// TODO: Add compile time shader loading like for SL shaders +inline void useExternalShader(AOptional& out, std::string_view vsPath, std::string_view fsPath) { + out.emplace(); + ALogger::info("OpenGL") << std::format("Loading vertex shader {}", vsPath); + std::ifstream vsFile{ static_cast(vsPath) }; + if (!vsFile.is_open()) { + throw AException("Couldn't open vertex shader " + vsPath); + } + ALogger::info("OpenGL") << std::format("Loading fragment shader {}", vsPath); + std::ifstream fsFile{ static_cast(fsPath) }; + if (!fsFile.is_open()) { + throw AException("Couldn't open fragment shader" + fsPath); + } + std::stringstream vsBuffer; + vsBuffer << vsFile.rdbuf(); + std::stringstream fsBuffer; + fsBuffer << fsFile.rdbuf(); + out->loadVertexShader(vsBuffer.str(), gl::GLSLOptions{.custom=true}); + out->loadFragmentShader(fsBuffer.str(), gl::GLSLOptions{.custom=true}); + out->compile(); +} + } OpenGLRenderer::OpenGLRenderer() { @@ -207,37 +233,41 @@ OpenGLRenderer::OpenGLRenderer() { mGradientTexture.bind(); mGradientTexture.setupLinear(); mGradientTexture.setupClampToEdge(); + useAuislShader(mSolidShader); - - useAuislShader(mBoxShadowShader); - - useAuislShader(mBoxShadowInnerShader); - - useAuislShader(mRoundedSolidShader); - useAuislShader(mRoundedSolidShaderBorder); - useAuislShader(mGradientShader); - useAuislShader(mRoundedGradientShader); - useAuislShader(mTexturedShader); - useAuislShader(mUnblendShader); - useAuislShader(mSquareSectorShader); - - useAuislShader(mSymbolShader); - useAuislShader(mSymbolShaderSubPixel); - - useAuislShader(mLineSolidDashedShader); + // useExternalShader(mSolidShader, "aui.views/shaders/basic.vert", "aui.views/shaders/solid.frag"); + // mSolidShader->bindAttribute(0, "pos"); + // mSolidShader->bindAttribute(1, "color"); + + // useAuislShader(mBoxShadowShader); + // + // useAuislShader(mBoxShadowInnerShader); + // + // useAuislShader(mRoundedSolidShader); + // useAuislShader(mRoundedSolidShaderBorder); + // useAuislShader(mGradientShader); + // useAuislShader(mRoundedGradientShader); + // useAuislShader(mTexturedShader); + // useAuislShader(mUnblendShader); + // useAuislShader(mSquareSectorShader); + // + // useAuislShader(mSymbolShader); + // useAuislShader(mSymbolShaderSubPixel); + // + // useAuislShader(mLineSolidDashedShader); { mRectangleVao.indicesByCount(BATCH_VERTEX_COUNT); @@ -245,8 +275,8 @@ OpenGLRenderer::OpenGLRenderer() { { mRectangleVao.indicesByCount(BATCH_VERTEX_COUNT); } - mBatchVerticies.fill(glm::vec3{0}); - mCurrentBatchVertex = mBatchVerticies.begin(); + mBatchVertices.fill(glm::vec3{0}); + mCurrentBatchVertex = mBatchVertices.begin(); } void OpenGLRenderer::handleCmds(std::vector cmds) { @@ -291,10 +321,15 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { }); auto &rectangleVao = mRectangleVao; - auto &batchVerticies = mBatchVerticies; + auto &batchVerticies = mBatchVertices; auto drawBatch = [&](const char *name) { - rectangleVao.insert(0, std::span{batchVerticies}, "Batch"); + rectangleVao.insert(0, std::span{batchVerticies}, name); rectangleVao.drawElements(); + // TODO: move this and make it more expandable + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 7, 0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 7, reinterpret_cast(3 * sizeof(float))); }; BatchId_t currentBatchId = 0; @@ -326,21 +361,22 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { std::visit(aui::lambda_overloaded{ [&](const CmdRectangle& c) { renderRectangle(cmd, c.brush, c.position, c.size, c.zIndex); }, - [&](const CmdRoundedRectangle& c) { renderRoundedRectangle(cmd, c.brush, c.position, c.size, c.radius, c.zIndex); }, - [&](const CmdRectangleBorder& c) { renderRectangleBorder(cmd, c.brush, c.position, c.size, c.lineWidth, c.zIndex); }, - [&](const CmdRoundedRectangleBorder& c) { renderRoundedRectangleBorder(cmd, c.brush, c.position, c.size, c.radius, c.borderWidth, c.zIndex); }, - [&](const CmdBoxShadow& c) { renderBoxShadow(cmd, c.position, c.size, c.blurRadius, c.color, c.zIndex); }, - [&](const CmdBoxShadowInner& c) { renderBoxShadowInner(cmd, c.position, c.size, c.blurRadius, c.spreadRadius, c.borderRadius, c.color, c.offset, c.zIndex); }, - [&](const CmdString& c) { renderString(cmd, c.position, c.string, c.fs); }, - [&](const CmdLines& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, - [&](const CmdPoints& c) { renderPoints(cmd, c.brush, c.points, c.size); }, - [&](const CmdLinesPairs& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, - [&](const CmdSquareSector& c) { renderSquareSector(cmd, c.brush, c.position, c.size, c.begin, c.end); }, - [&](const CmdSetWindow& c) { mWindow = c.window; }, - [&](const CmdNewRenderViewToTexture&){ /* handled elsewhere */ } + // [&](const CmdRoundedRectangle& c) { renderRoundedRectangle(cmd, c.brush, c.position, c.size, c.radius, c.zIndex); }, + // [&](const CmdRectangleBorder& c) { renderRectangleBorder(cmd, c.brush, c.position, c.size, c.lineWidth, c.zIndex); }, + // [&](const CmdRoundedRectangleBorder& c) { renderRoundedRectangleBorder(cmd, c.brush, c.position, c.size, c.radius, c.borderWidth, c.zIndex); }, + // [&](const CmdBoxShadow& c) { renderBoxShadow(cmd, c.position, c.size, c.blurRadius, c.color, c.zIndex); }, + // [&](const CmdBoxShadowInner& c) { renderBoxShadowInner(cmd, c.position, c.size, c.blurRadius, c.spreadRadius, c.borderRadius, c.color, c.offset, c.zIndex); }, + // [&](const CmdString& c) { renderString(cmd, c.position, c.string, c.fs); }, + // [&](const CmdLines& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, + // [&](const CmdPoints& c) { renderPoints(cmd, c.brush, c.points, c.size); }, + // [&](const CmdLinesPairs& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, + // [&](const CmdSquareSector& c) { renderSquareSector(cmd, c.brush, c.position, c.size, c.begin, c.end); }, + // [&](const CmdSetWindow& c) { mWindow = c.window; }, + // [&](const CmdNewRenderViewToTexture&){ /* handled elsewhere */ }, + [&](const auto &c){ } }, cmd.arg); } - if (mCurrentBatchVertex != mBatchVerticies.begin()) + if (mCurrentBatchVertex != mBatchVertices.begin()) drawBatch("Batch"); } @@ -366,9 +402,30 @@ std::array OpenGLRenderer::getVerticesForRect(glm::vec2 position, }; } +void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const int zIndex) { + ALogger::info("OpenGL") << "Rendering rectangle"; + appendRect(position, size, zIndex, cmd.transform); + + std::visit(aui::lambda_overloaded{ + [&](const ALinearGradientBrush& brush) { + // gradientBrush(cmd, brush, *this, *mGradientShader); + }, + [&](const ATexturedBrush& brush) { + // texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); + }, + [&](const ASolidBrush& brush) { + solidBrush(cmd, brush, *this, *mSolidShader); + }, + [](const ACustomShaderBrush& ) {}, + }, brush); +} + +void OpenGLRenderer::appendColor(const AColor color) { + *mCurrentBatchVertex++ = glm::vec4(color); +} + static constexpr size_t Z_DEPTH = 1000; -void OpenGLRenderer::appendBatchVerticiesForRect( - const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform) { +void OpenGLRenderer::appendRect(const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform) { float x = position.x; float y = position.y; float w = x + size.x; @@ -388,29 +445,6 @@ void OpenGLRenderer::appendBatchVerticiesForRect( } } -void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const int zIndex) { - std::visit(aui::lambda_overloaded{ - [&](const ALinearGradientBrush& brush) { - // gradientBrush(cmd, brush, *this, *mGradientShader); - }, - [&](const ATexturedBrush& brush) { - // texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); - }, - [&](const ASolidBrush& brush) { - solidBrush(cmd, brush, *this, *mSolidShader); - }, - [](const ACustomShaderBrush& ) {}, - }, brush); - - drawRectImpl(position, size, zIndex, cmd.transform); -} - -void OpenGLRenderer::drawRectImpl(const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform) { - mRectangleVao.bind(); - - appendBatchVerticiesForRect(position, size, zIndex, transform); -} - void OpenGLRenderer::identityUv() { const glm::vec2 uvs[] = { {0, 1}, @@ -426,6 +460,7 @@ void OpenGLRenderer::renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 size, float radius, const int zIndex) { + ALogger::info("OpenGL") << "Rendering rounded rectangle"; std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mRoundedGradientShader); }, @@ -436,7 +471,7 @@ void OpenGLRenderer::renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, identityUv(); gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_SIZE, 2.f * radius / size); - drawRectImpl(position, size, zIndex, cmd.transform); + appendRect(position, size, zIndex, cmd.transform); } void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, @@ -444,6 +479,7 @@ void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec2 size, float lineWidth, const int zIndex) { + ALogger::info("OpenGL") << "Rendering rectangle border"; std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, @@ -485,6 +521,7 @@ void OpenGLRenderer::renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& float radius, int borderWidth, const int zIndex) { + ALogger::info("OpenGL") << "Rendering rounded rectangle border"; std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, @@ -500,7 +537,7 @@ void OpenGLRenderer::renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_SIZE, 2.f * radius / size); gl::Program::currentShader()->set(aui::ShaderUniforms::INNER_SIZE, 2.f * (radius - borderWidth) / innerSize); gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_TO_INNER, size / innerSize); - drawRectImpl(position, size, zIndex, cmd.transform); + appendRect(position, size, zIndex, cmd.transform); } void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, @@ -508,6 +545,7 @@ void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, float blurRadius, const AColor& color, const int zIndex) { + ALogger::info("OpenGL") << "Rendering box shadow"; AUI_ASSERTX(blurRadius >= 0.f, "blurRadius is expected to be non negative, use boxShadowInner for inset shadows instead"); identityUv(); @@ -548,6 +586,7 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, const AColor& color, glm::vec2 offset, const int zIndex) { + ALogger::info("OpenGL") << "Rendering inner shadow"; AUI_ASSERTX(blurRadius >= 0.f, "blurRadius is expected to be non negative"); blurRadius *= -1.f; identityUv(); @@ -574,7 +613,7 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, // }; // mRectangleVao.insert(0, std::span{uvs}, "boxShadowInner"); - drawRectImpl(glm::vec2{x, y}, glm::vec2{w, h}, zIndex, cmd.transform); + appendRect(glm::vec2{x, y}, glm::vec2{w, h}, zIndex, cmd.transform); } void OpenGLRenderer::renderString(const Cmd& cmd, glm::vec2 position, @@ -1110,7 +1149,7 @@ void OpenGLRenderer::renderSquareSector(const Cmd& cmd, const ABrush& brush, gl::Program::currentShader()->set(aui::ShaderUniforms::M2, m2); // TODO: replace 0 with zIndex - drawRectImpl(position, size, 0, cmd.transform); + appendRect(position, size, 0, cmd.transform); } diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.h b/aui.views/src/AUI/GL/OpenGLRenderer.h index 731c7bd53..32e7a5222 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.h +++ b/aui.views/src/AUI/GL/OpenGLRenderer.h @@ -26,6 +26,8 @@ class OpenGLRenderer final: public IBatchingRenderer { friend class OpenGLPrerenderedString; friend class OpenGLMultiStringCanvas; public: + // TODO: Make this private, figure out how this should be accesible in brushes + void appendColor(const AColor color); struct FontEntryData: aui::noncopyable { Util::SimpleTexturePacker texturePacker; gl::Texture2D texture; @@ -70,7 +72,7 @@ friend class OpenGLMultiStringCanvas; AOptional mLineSolidDashedShader; static constexpr size_t MAX_BATCH_ELEMENTS = 1000; static constexpr size_t BATCH_VERTEX_COUNT = MAX_BATCH_ELEMENTS * 4; - std::array mBatchVerticies; + std::array mBatchVertices; std::array::iterator mCurrentBatchVertex; gl::Vao mRectangleVao; gl::Vao mBorderVao; @@ -105,7 +107,6 @@ friend class OpenGLMultiStringCanvas; static std::array getVerticesForRect(glm::vec2 position, glm::vec2 size); - void appendBatchVerticiesForRect(const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform); FontEntryData* getFontEntryData(const AFontStyle& fontStyle); @@ -134,7 +135,7 @@ friend class OpenGLMultiStringCanvas; */ FramebufferFromPool getFramebufferForMultiPassEffect(glm::uvec2 minRequiredSize); - void drawRectImpl(const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform); + void appendRect(const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform); private: diff --git a/aui.views/src/AUI/GL/Vao.cpp b/aui.views/src/AUI/GL/Vao.cpp index 9fce95464..aae8d7417 100644 --- a/aui.views/src/AUI/GL/Vao.cpp +++ b/aui.views/src/AUI/GL/Vao.cpp @@ -94,12 +94,12 @@ void gl::Vao::insert( mBuffers[index].lastModifierKey = key; - auto signature = uint32_t(vertexSize) ^ dataType; - if (newFlag || mBuffers[index].signature != signature) { - glEnableVertexAttribArray(index); - glVertexAttribPointer(index, vertexSize, dataType, GL_FALSE, 0, nullptr); - mBuffers[index].signature = signature; - } + // auto signature = uint32_t(vertexSize) ^ dataType; + // if (newFlag || mBuffers[index].signature != signature) { + // glEnableVertexAttribArray(index); + // glVertexAttribPointer(index, vertexSize, dataType, GL_FALSE, 0, nullptr); + // mBuffers[index].signature = signature; + // } } void gl::Vao::insertInteger(GLuint index, const char* data, GLsizeiptr dataSize, GLuint vertexSize, GLenum dataType) { From c668b8e10bb417e2e456423b5bfe34d0b89fed67 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Thu, 5 Mar 2026 13:17:00 +0300 Subject: [PATCH 18/22] minor fixes --- aui.core/src/AUI/Common/AMap.h | 9 ++++----- aui.core/src/AUI/Common/AString.h | 5 +---- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 20 ++++++-------------- aui.views/src/AUI/SL/SL.h | 2 -- examples/ui/game_inventory/src/main.cpp | 7 +++++-- 5 files changed, 16 insertions(+), 27 deletions(-) diff --git a/aui.core/src/AUI/Common/AMap.h b/aui.core/src/AUI/Common/AMap.h index 96711a1e1..fceca837c 100644 --- a/aui.core/src/AUI/Common/AMap.h +++ b/aui.core/src/AUI/Common/AMap.h @@ -12,7 +12,6 @@ #pragma once #include #include -#include "AUI/Core.h" #include "AException.h" #include #include @@ -59,19 +58,19 @@ class ABaseMap: public Parent private: iterator mIterator; bool mValid; - + public: contains_iterator(const iterator& p, bool valid): mIterator(p), mValid(valid) { - + } contains_iterator(const contains_iterator& c): mIterator(c.mIterator), mValid(c.mValid) { - + } operator bool() const noexcept { @@ -259,4 +258,4 @@ inline auto aui::container::to_unordered_map(Iterator begin, result[std::move(key)] = std::move(value); } return result; -} \ No newline at end of file +} diff --git a/aui.core/src/AUI/Common/AString.h b/aui.core/src/AUI/Common/AString.h index 2044ebf77..f43af840b 100644 --- a/aui.core/src/AUI/Common/AString.h +++ b/aui.core/src/AUI/Common/AString.h @@ -11,7 +11,6 @@ #pragma once -#include #include #include #include @@ -20,9 +19,7 @@ #include #include #include -#include #include -#include #include #if AUI_PLATFORM_ANDROID #include @@ -288,7 +285,7 @@ class API_AUI_CORE AString: public std::string { AString(AChar c); AString(size_type n, AChar c); - + AString(size_type n, char32_t c) : AString(n, AChar(c)) {} AString(size_type n, char16_t c) : AString(n, AChar(c)) {} diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index 414edb099..beaa81339 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -30,7 +30,6 @@ #include "AUI/GL/Texture2D.h" #include "AUI/GL/Vao.h" #include "AUI/GL/gl.h" -#include "AUI/Platform/AInput.h" #include "AUI/Platform/APlatform.h" #include "AUI/Render/ABorderStyle.h" #include "AUI/Render/ABrush.h" @@ -128,7 +127,6 @@ void gradientBrush(const IBatchingRenderer::Cmd& cmd, const ALinearGradientBrush void solidBrush(const IBatchingRenderer::Cmd& cmd, const ASolidBrush& brush, OpenGLRenderer& renderer, gl::Program& shader) { shader.use(); - ALogger::info("OpenGL") << "Brush color: " << cmd.color.toString(); renderer.appendColor(cmd.color * brush.solidColor); } @@ -199,7 +197,7 @@ inline void useExternalShader(AOptional& out, std::string_view vsPa if (!vsFile.is_open()) { throw AException("Couldn't open vertex shader " + vsPath); } - ALogger::info("OpenGL") << std::format("Loading fragment shader {}", vsPath); + ALogger::info("OpenGL") << std::format("Loading fragment shader {}", fsPath); std::ifstream fsFile{ static_cast(fsPath) }; if (!fsFile.is_open()) { throw AException("Couldn't open fragment shader" + fsPath); @@ -234,11 +232,11 @@ OpenGLRenderer::OpenGLRenderer() { mGradientTexture.setupLinear(); mGradientTexture.setupClampToEdge(); - useAuislShader(mSolidShader); - // useExternalShader(mSolidShader, "aui.views/shaders/basic.vert", "aui.views/shaders/solid.frag"); - // mSolidShader->bindAttribute(0, "pos"); - // mSolidShader->bindAttribute(1, "color"); + // useAuislShader(mSolidShader); + useExternalShader(mSolidShader, "aui.views/shaders/basic.vert", "aui.views/shaders/solid.frag"); + mSolidShader->bindAttribute(0, "pos"); + mSolidShader->bindAttribute(1, "color"); // useAuislShader(mBoxShadowShader); @@ -403,7 +401,6 @@ std::array OpenGLRenderer::getVerticesForRect(glm::vec2 position, } void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const int zIndex) { - ALogger::info("OpenGL") << "Rendering rectangle"; appendRect(position, size, zIndex, cmd.transform); std::visit(aui::lambda_overloaded{ @@ -460,7 +457,6 @@ void OpenGLRenderer::renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 size, float radius, const int zIndex) { - ALogger::info("OpenGL") << "Rendering rounded rectangle"; std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mRoundedGradientShader); }, @@ -479,7 +475,6 @@ void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec2 size, float lineWidth, const int zIndex) { - ALogger::info("OpenGL") << "Rendering rectangle border"; std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, @@ -521,7 +516,6 @@ void OpenGLRenderer::renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& float radius, int borderWidth, const int zIndex) { - ALogger::info("OpenGL") << "Rendering rounded rectangle border"; std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, @@ -545,7 +539,6 @@ void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, float blurRadius, const AColor& color, const int zIndex) { - ALogger::info("OpenGL") << "Rendering box shadow"; AUI_ASSERTX(blurRadius >= 0.f, "blurRadius is expected to be non negative, use boxShadowInner for inset shadows instead"); identityUv(); @@ -586,7 +579,6 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, const AColor& color, glm::vec2 offset, const int zIndex) { - ALogger::info("OpenGL") << "Rendering inner shadow"; AUI_ASSERTX(blurRadius >= 0.f, "blurRadius is expected to be non negative"); blurRadius *= -1.f; identityUv(); diff --git a/aui.views/src/AUI/SL/SL.h b/aui.views/src/AUI/SL/SL.h index 96f9a0f57..80ed275b8 100644 --- a/aui.views/src/AUI/SL/SL.h +++ b/aui.views/src/AUI/SL/SL.h @@ -12,9 +12,7 @@ #pragma once #include "AUI/Enum/ImageRendering.h" -#include "AUI/Image/AImage.h" #include "glm/common.hpp" -#include "glm/ext/quaternion_common.hpp" #include "glm/fwd.hpp" #include #include diff --git a/examples/ui/game_inventory/src/main.cpp b/examples/ui/game_inventory/src/main.cpp index 2c2c5c3ab..8f708bd26 100644 --- a/examples/ui/game_inventory/src/main.cpp +++ b/examples/ui/game_inventory/src/main.cpp @@ -9,6 +9,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "AUI/ASS/Property/BackgroundSolid.h" +#include "AUI/Common/AColor.h" #include "AUI/Platform/ARenderingContextOptions.h" #include "AUI/View/AForEachUI.h" #include "AUI/View/AScrollArea.h" @@ -51,7 +53,8 @@ _ itemStackView(const _>>& itemStack) { _new() AUI_LET { AObject::connect( AUI_REACT(ass::PropertyListRecursive { - BackgroundImage { (*itemStack) ->hasValue() ? ":texture/item/{}.png"_format((**itemStack)->id) : "" }, + // BackgroundImage { (*itemStack) ->hasValue() ? ":texture/item/{}.png"_format((**itemStack)->id) : "" }, + BackgroundSolid{ AColor{ 1.0, 1.0, 1.0}}, Expanding {}, }), AUI_SLOT(it)::setCustomStyle); @@ -126,7 +129,7 @@ AUI_ENTRY { window->setContents( Centered { Vertical { - Label { "Inventory" } AUI_OVERRIDE_STYLE { FontSize { 32_dp } }, + // Label { "Inventory" } AUI_OVERRIDE_STYLE { FontSize { 32_dp } }, inventoryGrid(state), } AUI_OVERRIDE_STYLE { Expanding {}, From 0fb6dc2a475f908bc120bd735def54eeb7d232c4 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Tue, 10 Mar 2026 01:05:19 +0300 Subject: [PATCH 19/22] batching: solid and basic shader done + transparency fix WIP --- aui.uitests/src/AUI/Test/UI/UITestCase.cpp | 1 + aui.views/shaders/basic.vert | 5 +- aui.views/shaders/solid.frag | 2 +- .../AUI/ASS/Property/BackgroundGradient.cpp | 4 +- .../src/AUI/ASS/Property/BackgroundImage.cpp | 4 +- .../src/AUI/ASS/Property/BackgroundSolid.cpp | 2 + aui.views/src/AUI/ASS/Property/Border.cpp | 3 +- .../src/AUI/ASS/Property/BorderBottom.cpp | 3 +- aui.views/src/AUI/ASS/Property/BorderLeft.cpp | 3 +- .../src/AUI/ASS/Property/BorderRight.cpp | 3 +- aui.views/src/AUI/ASS/Property/BorderTop.cpp | 3 +- aui.views/src/AUI/ASS/Property/BoxShadow.cpp | 1 + .../src/AUI/ASS/Property/BoxShadowInner.cpp | 3 +- aui.views/src/AUI/Animator/AFocusAnimator.cpp | 1 + .../AUI/Devtools/DevtoolsPerformanceTab.cpp | 10 +- .../src/AUI/Devtools/DevtoolsThreadsTab.cpp | 2 +- aui.views/src/AUI/GL/IBatchingRenderer.cpp | 24 ++-- aui.views/src/AUI/GL/IBatchingRenderer.h | 37 +++--- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 113 ++++++++---------- aui.views/src/AUI/GL/OpenGLRenderer.h | 57 ++++++--- aui.views/src/AUI/Image/AAnimatedDrawable.cpp | 3 +- aui.views/src/AUI/Image/SvgDrawable.cpp | 2 + aui.views/src/AUI/Render/ABrush.h | 2 + aui.views/src/AUI/Render/ARenderContext.h | 2 +- aui.views/src/AUI/Render/IRenderer.cpp | 3 +- aui.views/src/AUI/Render/IRenderer.h | 10 +- .../src/AUI/Software/SoftwareRenderer.cpp | 22 ++-- aui.views/src/AUI/Software/SoftwareRenderer.h | 8 +- aui.views/src/AUI/Util/ACursorSelectable.h | 3 +- aui.views/src/AUI/Util/ANoiseDrawable.cpp | 3 +- aui.views/src/AUI/Util/AStubWindowManager.h | 2 +- aui.views/src/AUI/Util/AViewProfiler.cpp | 4 + aui.views/src/AUI/Util/ImageDrawable.cpp | 3 +- aui.views/src/AUI/View/AAbstractTypeable.cpp | 3 +- aui.views/src/AUI/View/AGroupBox.cpp | 1 + aui.views/src/AUI/View/ARulerArea.cpp | 3 + aui.views/src/AUI/View/ARulerView.cpp | 8 +- aui.views/src/AUI/View/AView.cpp | 8 ++ aui.views/src/AUI/View/AView.h | 13 ++ aui.views/src/AUI/View/AViewContainerBase.cpp | 7 +- examples/7guis/circle_drawer/src/main.cpp | 6 +- examples/app/fractal/src/FractalView.cpp | 2 +- examples/app/game_of_life/src/main.cpp | 2 +- examples/ui/game_inventory/src/main.cpp | 5 +- 44 files changed, 252 insertions(+), 154 deletions(-) diff --git a/aui.uitests/src/AUI/Test/UI/UITestCase.cpp b/aui.uitests/src/AUI/Test/UI/UITestCase.cpp index 92b9b888d..7caac1078 100644 --- a/aui.uitests/src/AUI/Test/UI/UITestCase.cpp +++ b/aui.uitests/src/AUI/Test/UI/UITestCase.cpp @@ -48,6 +48,7 @@ class MyListener: public ::testing::EmptyTestEventListener { for (auto& v: matcher->toSet()) { AWindow::current()->getRenderingContext()->renderer().rectangleBorder(ASolidBrush{0xaae00000_argb}, v->getPositionInWindow() - glm::ivec2{1, 1}, + v->getZIndex(), v->getSize() + glm::ivec2{2, 2}); } } diff --git a/aui.views/shaders/basic.vert b/aui.views/shaders/basic.vert index ce8a76f0e..09f9060c8 100644 --- a/aui.views/shaders/basic.vert +++ b/aui.views/shaders/basic.vert @@ -2,10 +2,11 @@ precision highp float; -layout(location = 0) in vec3 pos; +layout(location = 0) in vec4 pos; layout(location = 1) in vec4 color; flat out vec4 vertexColor; void main() { - gl_Position = vec4(pos.xyz, 1); + gl_Position = vec4(pos); + vertexColor = color; } diff --git a/aui.views/shaders/solid.frag b/aui.views/shaders/solid.frag index a90644509..f57bacc81 100644 --- a/aui.views/shaders/solid.frag +++ b/aui.views/shaders/solid.frag @@ -6,5 +6,5 @@ flat in vec4 vertexColor; out vec4 fragColor; void main() { - fragColor = vertexColor; + fragColor = vertexColor; } diff --git a/aui.views/src/AUI/ASS/Property/BackgroundGradient.cpp b/aui.views/src/AUI/ASS/Property/BackgroundGradient.cpp index e560d1c44..0d44fc6f9 100644 --- a/aui.views/src/AUI/ASS/Property/BackgroundGradient.cpp +++ b/aui.views/src/AUI/ASS/Property/BackgroundGradient.cpp @@ -24,9 +24,9 @@ void ass::prop::Property::renderFor(AView* view, const RenderHints::PushColor x(ctx.render); if (view->getBorderRadius() > 0) { - ctx.render.roundedRectangle(ABrush(*mInfo.gradient), {0, 0}, view->getSize(), view->getBorderRadius()); + ctx.render.roundedRectangle(ABrush(*mInfo.gradient), {0, 0}, view->getZIndex(), view->getSize(), view->getBorderRadius()); } else { - ctx.render.rectangle(ABrush(*mInfo.gradient), {0, 0}, view->getSize()); + ctx.render.rectangle(ABrush(*mInfo.gradient), {0, 0}, view->getZIndex(), view->getSize()); } IPropertyBase::renderFor(view, ctx); } diff --git a/aui.views/src/AUI/ASS/Property/BackgroundImage.cpp b/aui.views/src/AUI/ASS/Property/BackgroundImage.cpp index 0988505bf..42f350e96 100644 --- a/aui.views/src/AUI/ASS/Property/BackgroundImage.cpp +++ b/aui.views/src/AUI/ASS/Property/BackgroundImage.cpp @@ -252,7 +252,7 @@ void ass::prop::Property::draw( glm::translate(glm::mat4(1.f), glm::vec3 { glm::vec2(viewSize - imageSize) / 2.f, 0.f })); RenderHints::PushMask mask(ctx.render, [&] { - ctx.render.rectangle(ASolidBrush {}, { 0, 0 }, view->getSize()); + ctx.render.rectangle(ASolidBrush {}, { 0, 0 }, view->getZIndex(), view->getSize()); }); drawableDrawWrapper(imageSize); @@ -260,7 +260,7 @@ void ass::prop::Property::draw( } case Sizing::NONE: { RenderHints::PushMask mask(ctx.render, [&] { - ctx.render.rectangle(ASolidBrush {}, { 0, 0 }, view->getSize()); + ctx.render.rectangle(ASolidBrush {}, { 0, 0 }, view->getZIndex(), view->getSize()); }); glm::vec2 imageSize = glm::vec2(drawable->getSizeHint()); diff --git a/aui.views/src/AUI/ASS/Property/BackgroundSolid.cpp b/aui.views/src/AUI/ASS/Property/BackgroundSolid.cpp index f01917828..9e95d4b58 100644 --- a/aui.views/src/AUI/ASS/Property/BackgroundSolid.cpp +++ b/aui.views/src/AUI/ASS/Property/BackgroundSolid.cpp @@ -23,11 +23,13 @@ void ass::prop::Property::renderFor(AView* view, const ARe if (view->getBorderRadius() > 0) { ctx.render.roundedRectangle(brush, {0, 0}, + view->getZIndex(), view->getSize(), view->getBorderRadius()); } else { ctx.render.rectangle(brush, {0, 0}, + view->getZIndex(), view->getSize()); } diff --git a/aui.views/src/AUI/ASS/Property/Border.cpp b/aui.views/src/AUI/ASS/Property/Border.cpp index 5946a809e..09e2bc996 100644 --- a/aui.views/src/AUI/ASS/Property/Border.cpp +++ b/aui.views/src/AUI/ASS/Property/Border.cpp @@ -29,6 +29,7 @@ void ass::prop::Property::renderFor(AView* view, const ARenderConte */ ctx.render.roundedRectangleBorder(ASolidBrush{mInfo.color}, {0, 0}, + view->getZIndex(), view->getSize(), view->getBorderRadius(), mInfo.width); @@ -41,4 +42,4 @@ bool ass::prop::Property::isNone() { ass::prop::PropertySlot ass::prop::Property::getPropertySlot() const { return ass::prop::PropertySlot::BORDER; -} \ No newline at end of file +} diff --git a/aui.views/src/AUI/ASS/Property/BorderBottom.cpp b/aui.views/src/AUI/ASS/Property/BorderBottom.cpp index 6bf89364a..ede842f40 100644 --- a/aui.views/src/AUI/ASS/Property/BorderBottom.cpp +++ b/aui.views/src/AUI/ASS/Property/BorderBottom.cpp @@ -21,6 +21,7 @@ void ass::prop::Property::renderFor(AView* view, const ARende int w = mInfo.width; ctx.render.rectangle(ASolidBrush{mInfo.color}, {0, view->getHeight() - w}, + view->getZIndex(), {view->getWidth(), w}); } @@ -30,4 +31,4 @@ bool ass::prop::Property::isNone() { ass::prop::PropertySlot ass::prop::Property::getPropertySlot() const { return ass::prop::PropertySlot::BORDER; -} \ No newline at end of file +} diff --git a/aui.views/src/AUI/ASS/Property/BorderLeft.cpp b/aui.views/src/AUI/ASS/Property/BorderLeft.cpp index 99a3a3f40..a691a77f7 100644 --- a/aui.views/src/AUI/ASS/Property/BorderLeft.cpp +++ b/aui.views/src/AUI/ASS/Property/BorderLeft.cpp @@ -22,6 +22,7 @@ void ass::prop::Property::renderFor(AView* view, const ARenderC ctx.render.rectangle(ASolidBrush{mInfo.color}, {0, 0}, + view->getZIndex(), {w, view->getHeight()}); } @@ -32,4 +33,4 @@ bool ass::prop::Property::isNone() { ass::prop::PropertySlot ass::prop::Property::getPropertySlot() const { return ass::prop::PropertySlot::BORDER; -} \ No newline at end of file +} diff --git a/aui.views/src/AUI/ASS/Property/BorderRight.cpp b/aui.views/src/AUI/ASS/Property/BorderRight.cpp index 075fd8a98..8d4f719ea 100644 --- a/aui.views/src/AUI/ASS/Property/BorderRight.cpp +++ b/aui.views/src/AUI/ASS/Property/BorderRight.cpp @@ -18,6 +18,7 @@ void ass::prop::Property::renderFor(AView* view, const ARender ctx.render.rectangle(ASolidBrush{mInfo.color}, {view->getWidth() - w, 0}, + view->getZIndex(), {w, view->getHeight()}); } @@ -28,4 +29,4 @@ bool ass::prop::Property::isNone() { ass::prop::PropertySlot ass::prop::Property::getPropertySlot() const { return ass::prop::PropertySlot::BORDER; -} \ No newline at end of file +} diff --git a/aui.views/src/AUI/ASS/Property/BorderTop.cpp b/aui.views/src/AUI/ASS/Property/BorderTop.cpp index e576a06df..049ec6092 100644 --- a/aui.views/src/AUI/ASS/Property/BorderTop.cpp +++ b/aui.views/src/AUI/ASS/Property/BorderTop.cpp @@ -17,6 +17,7 @@ void ass::prop::Property::renderFor(AView* view, const ARenderCo int w = mInfo.width; ctx.render.rectangle(ASolidBrush{mInfo.color}, {0, 0}, + view->getZIndex(), {view->getWidth(), w}); } @@ -26,4 +27,4 @@ bool ass::prop::Property::isNone() { ass::prop::PropertySlot ass::prop::Property::getPropertySlot() const { return ass::prop::PropertySlot::BORDER; -} \ No newline at end of file +} diff --git a/aui.views/src/AUI/ASS/Property/BoxShadow.cpp b/aui.views/src/AUI/ASS/Property/BoxShadow.cpp index 6f6e200f8..066de9bcb 100644 --- a/aui.views/src/AUI/ASS/Property/BoxShadow.cpp +++ b/aui.views/src/AUI/ASS/Property/BoxShadow.cpp @@ -20,6 +20,7 @@ void ass::prop::Property::renderFor(AView* view, const ARenderContext& ctx) { ctx.render.boxShadow({mInfo.offsetX.getValuePx() - mInfo.spreadRadius.getValuePx(), mInfo.offsetY.getValuePx() - mInfo.spreadRadius.getValuePx()}, + view->getZIndex(), glm::vec2(view->getSize()) + mInfo.spreadRadius.getValuePx() * 2.f, mInfo.blurRadius, mInfo.color); diff --git a/aui.views/src/AUI/ASS/Property/BoxShadowInner.cpp b/aui.views/src/AUI/ASS/Property/BoxShadowInner.cpp index c6543db9d..2c0405674 100644 --- a/aui.views/src/AUI/ASS/Property/BoxShadowInner.cpp +++ b/aui.views/src/AUI/ASS/Property/BoxShadowInner.cpp @@ -19,6 +19,7 @@ void ass::prop::Property::renderFor(AView* view, const ARenderContext& ctx) { ctx.render.boxShadowInner({0, 0}, + view->getZIndex(), glm::vec2(view->getSize()), mInfo.blurRadius, mInfo.spreadRadius, @@ -33,4 +34,4 @@ ass::prop::PropertySlot ass::prop::Property::getPropertySlo bool ass::prop::Property::isNone() { return mInfo.color.isFullyTransparent(); -} \ No newline at end of file +} diff --git a/aui.views/src/AUI/Animator/AFocusAnimator.cpp b/aui.views/src/AUI/Animator/AFocusAnimator.cpp index 0eb507c3b..ac94812bf 100644 --- a/aui.views/src/AUI/Animator/AFocusAnimator.cpp +++ b/aui.views/src/AUI/Animator/AFocusAnimator.cpp @@ -29,6 +29,7 @@ void AFocusAnimator::doAnimation(AView* view, float theta, IRenderer& render) { render.rectangleBorder( ASolidBrush{{0, 0, 0, t}}, {-t * SIZE, -t * SIZE}, + view->getZIndex(), {t * SIZE * 2 + view->getWidth(), t * SIZE * 2 + view->getHeight()}, 2.f); } diff --git a/aui.views/src/AUI/Devtools/DevtoolsPerformanceTab.cpp b/aui.views/src/AUI/Devtools/DevtoolsPerformanceTab.cpp index 1f90446fa..5fcb2e2b3 100644 --- a/aui.views/src/AUI/Devtools/DevtoolsPerformanceTab.cpp +++ b/aui.views/src/AUI/Devtools/DevtoolsPerformanceTab.cpp @@ -73,18 +73,18 @@ namespace { ctx.render.rectangle(ATexturedBrush { .texture = mTexture, .imageRendering = ImageRendering::PIXELATED, - }, {0, 0}, mImage.size() * plotScale()); + }, {0, 0}, mZIndex, mImage.size() * plotScale()); if (!mSelectionMode) { return; } if (mHoveredFrameIndex && !mSelectedFrameIndex) { - ctx.render.rectangle(ASolidBrush {AColor::WHITE.transparentize(0.6f) }, {*mHoveredFrameIndex * plotScale(), 0}, {plotScale(), getSize().y}); + ctx.render.rectangle(ASolidBrush {AColor::WHITE.transparentize(0.6f) }, {*mHoveredFrameIndex * plotScale(), 0}, mZIndex, {plotScale(), getSize().y}); } if (mSelectedFrameIndex) { - ctx.render.rectangle(ASolidBrush {AColor::WHITE.transparentize(0.5f) }, {*mSelectedFrameIndex * plotScale(), 0}, {plotScale(), getSize().y}); + ctx.render.rectangle(ASolidBrush {AColor::WHITE.transparentize(0.5f) }, {*mSelectedFrameIndex * plotScale(), 0}, mZIndex, {plotScale(), getSize().y}); } } @@ -327,7 +327,7 @@ DevtoolsPerformanceTab::DevtoolsPerformanceTab(AWindowBase* targetWindow) : mTar lastTimeUpdated = now; treeView->onPerformanceFrame(sections); - }); + }); connect(graphView->selectionChanged, AUI_SLOT(treeView)::onPerformanceFrame); connect(mState, [=](const State& state) { @@ -384,7 +384,7 @@ DevtoolsPerformanceTab::DevtoolsPerformanceTab(AWindowBase* targetWindow) : mTar }, }, }, - }); + }); #else setContents(Centered { Label { "Please set -DAUI_PROFILING=TRUE in CMake configure." } diff --git a/aui.views/src/AUI/Devtools/DevtoolsThreadsTab.cpp b/aui.views/src/AUI/Devtools/DevtoolsThreadsTab.cpp index c2f0115b4..0d4ac1447 100644 --- a/aui.views/src/AUI/Devtools/DevtoolsThreadsTab.cpp +++ b/aui.views/src/AUI/Devtools/DevtoolsThreadsTab.cpp @@ -74,7 +74,7 @@ class WatcherView : public ALabel { color = 0xff0000_rgb; paint: - ctx.render.rectangle(ASolidBrush { color }, { 0, 0 }, getSize()); + ctx.render.rectangle(ASolidBrush { color }, { 0, 0 }, mZIndex, getSize()); } }; } // namespace diff --git a/aui.views/src/AUI/GL/IBatchingRenderer.cpp b/aui.views/src/AUI/GL/IBatchingRenderer.cpp index b058e1a0a..9898f1373 100644 --- a/aui.views/src/AUI/GL/IBatchingRenderer.cpp +++ b/aui.views/src/AUI/GL/IBatchingRenderer.cpp @@ -13,57 +13,57 @@ #include "IBatchingRenderer.h" -void IBatchingRenderer::rectangle(const ABrush& brush, glm::vec2 position, glm::vec2 size) { +void IBatchingRenderer::rectangle(const ABrush& brush, glm::vec2 position, zIndex_t zIndex, glm::vec2 size) { enqueueCommand(CmdRectangle { .brush = std::move(brush), .position = position, .size = size, - .zIndex = static_cast(mCmds.size()) + 1 + .zIndex = zIndex }); } -void IBatchingRenderer::roundedRectangle(const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius) { +void IBatchingRenderer::roundedRectangle(const ABrush& brush, glm::vec2 position, zIndex_t zIndex, glm::vec2 size, float radius) { enqueueCommand(CmdRoundedRectangle{ .brush = brush, .position = position, .size = size, .radius = radius, - .zIndex = static_cast(mCmds.size()) + 1 + .zIndex = zIndex }); } -void IBatchingRenderer::rectangleBorder(const ABrush& brush, glm::vec2 position, glm::vec2 size, float lineWidth) { +void IBatchingRenderer::rectangleBorder(const ABrush& brush, glm::vec2 position, zIndex_t zIndex, glm::vec2 size, float lineWidth) { enqueueCommand(CmdRectangleBorder{ .brush = brush, .position = position, .size = size, .lineWidth = lineWidth, - .zIndex = static_cast(mCmds.size()) + 1 + .zIndex = zIndex }); } -void IBatchingRenderer::roundedRectangleBorder(const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, int borderWidth) { +void IBatchingRenderer::roundedRectangleBorder(const ABrush& brush, glm::vec2 position, zIndex_t zIndex, glm::vec2 size, float radius, int borderWidth) { enqueueCommand(CmdRoundedRectangleBorder{ .brush = brush, .position = position, .size = size, .radius = radius, .borderWidth = borderWidth, - .zIndex = static_cast(mCmds.size()) + 1 + .zIndex = zIndex }); } -void IBatchingRenderer::boxShadow(glm::vec2 position, glm::vec2 size, float blurRadius, const AColor& color) { +void IBatchingRenderer::boxShadow(glm::vec2 position, zIndex_t zIndex, glm::vec2 size, float blurRadius, const AColor& color) { enqueueCommand(CmdBoxShadow{ .position = position, .size = size, .blurRadius = blurRadius, .color = color, - .zIndex = static_cast(mCmds.size()) + 1 + .zIndex = zIndex }); } -void IBatchingRenderer::boxShadowInner(glm::vec2 position, glm::vec2 size, float blurRadius, float spreadRadius, float borderRadius, const AColor& color, glm::vec2 offset) { +void IBatchingRenderer::boxShadowInner(glm::vec2 position, zIndex_t zIndex, glm::vec2 size, float blurRadius, float spreadRadius, float borderRadius, const AColor& color, glm::vec2 offset) { enqueueCommand(CmdBoxShadowInner{ .position = position, .size = size, @@ -72,7 +72,7 @@ void IBatchingRenderer::boxShadowInner(glm::vec2 position, glm::vec2 size, float .borderRadius = borderRadius, .color = color, .offset = offset, - .zIndex = static_cast(mCmds.size()) + 1 + .zIndex = zIndex }); } diff --git a/aui.views/src/AUI/GL/IBatchingRenderer.h b/aui.views/src/AUI/GL/IBatchingRenderer.h index d9620025c..14605d1b7 100644 --- a/aui.views/src/AUI/GL/IBatchingRenderer.h +++ b/aui.views/src/AUI/GL/IBatchingRenderer.h @@ -18,21 +18,21 @@ class IBatchingRenderer : public IRenderer { ABrush brush; glm::vec2 position; glm::vec2 size; - int zIndex; + zIndex_t zIndex; }; struct CmdRoundedRectangle { ABrush brush; glm::vec2 position; glm::vec2 size; float radius; - int zIndex; + zIndex_t zIndex; }; struct CmdRectangleBorder { ABrush brush; glm::vec2 position; glm::vec2 size; float lineWidth; - int zIndex; + zIndex_t zIndex; }; struct CmdRoundedRectangleBorder { ABrush brush; @@ -40,14 +40,14 @@ class IBatchingRenderer : public IRenderer { glm::vec2 size; float radius; int borderWidth; - int zIndex; + zIndex_t zIndex; }; struct CmdBoxShadow { glm::vec2 position; glm::vec2 size; float blurRadius; AColor color; - int zIndex; + zIndex_t zIndex; }; struct CmdBoxShadowInner { glm::vec2 position; @@ -57,7 +57,7 @@ class IBatchingRenderer : public IRenderer { float borderRadius; AColor color; glm::vec2 offset; - int zIndex; + zIndex_t zIndex; }; struct CmdString { glm::vec2 position; @@ -92,14 +92,19 @@ class IBatchingRenderer : public IRenderer { struct CmdSetWindow { AWindowBase* window; }; - using BatchId_t = uint16_t; + using BatchId_t = uint32_t; union BatchId { + BatchId_t value; struct { - unsigned char cmdId : 8; unsigned char brushId : 8; - // uint16_t zIndex : 16; + unsigned char cmdId : 8; + zIndex_t zIndex : 16; }; - BatchId_t value; + // TODO: finish bit order fix + // static BatchId new(int16_t z, uint8_t cmd, uint8_t brush) { + // return { static_cast(z << 16) | static_cast(cmd << 8) | static_cast(brush) }; + // } + // auto operator<=>(const BatchId&) const = default; }; struct Cmd { glm::mat4 transform; @@ -113,14 +118,14 @@ class IBatchingRenderer : public IRenderer { }; ~IBatchingRenderer() override = default; - void rectangle(const ABrush& brush, glm::vec2 position, glm::vec2 size) override; - void roundedRectangle(const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius) override; - void rectangleBorder(const ABrush& brush, glm::vec2 position, glm::vec2 size, float lineWidth) override; + void rectangle(const ABrush& brush, glm::vec2 position, zIndex_t zIndex, glm::vec2 size) override; + void roundedRectangle(const ABrush& brush, glm::vec2 position, zIndex_t zIndex, glm::vec2 size, float radius) override; + void rectangleBorder(const ABrush& brush, glm::vec2 position, zIndex_t zIndex, glm::vec2 size, float lineWidth) override; void roundedRectangleBorder( - const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, int borderWidth) override; - void boxShadow(glm::vec2 position, glm::vec2 size, float blurRadius, const AColor& color) override; + const ABrush& brush, glm::vec2 position, zIndex_t zIndex, glm::vec2 size, float radius, int borderWidth) override; + void boxShadow(glm::vec2 position, zIndex_t zIndex, glm::vec2 size, float blurRadius, const AColor& color) override; void boxShadowInner( - glm::vec2 position, glm::vec2 size, float blurRadius, float spreadRadius, float borderRadius, + glm::vec2 position, zIndex_t zIndex, glm::vec2 size, float blurRadius, float spreadRadius, float borderRadius, const AColor& color, glm::vec2 offset) override; void string(glm::vec2 position, const AString& string, const AFontStyle& fs) override; void lines(const ABrush& brush, AArrayView points, const ABorderStyle& style, AMetric width) override; diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index beaa81339..f4e1e2871 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +43,7 @@ #include "glm/fwd.hpp" #include "AUI/Util/GaussianKernel.h" #include "AUI/Traits/bit.h" +#include "glm/gtc/type_ptr.hpp" #include #include #include @@ -125,11 +127,6 @@ void gradientBrush(const IBatchingRenderer::Cmd& cmd, const ALinearGradientBrush renderer.identityUv(); } -void solidBrush(const IBatchingRenderer::Cmd& cmd, const ASolidBrush& brush, OpenGLRenderer& renderer, gl::Program& shader) { - shader.use(); - renderer.appendColor(cmd.color * brush.solidColor); -} - void texturedBrush(const IBatchingRenderer::Cmd& cmd, const ATexturedBrush& brush, OpenGLRenderer& renderer, gl::Program& shader, gl::Vao& tempVao) { shader.use(); shader.set(aui::ShaderUniforms::COLOR, cmd.color); @@ -213,6 +210,14 @@ inline void useExternalShader(AOptional& out, std::string_view vsPa } +ASolidBrush::Data OpenGLRenderer::solidBrush(const IBatchingRenderer::Cmd& cmd, const ASolidBrush& brush, OpenGLRenderer& renderer, gl::Program& shader) { + mBatchShader = &shader; + auto color = cmd.color * brush.solidColor; + color.a = 0.5; + + return color; +} + OpenGLRenderer::OpenGLRenderer() { ALogger::info(LOG_TAG) << "GL_VERSION = " << ((const char*) glGetString(GL_VERSION)); ALogger::info(LOG_TAG) << "GL_VENDOR = " << ((const char*) glGetString(GL_VENDOR)); @@ -268,17 +273,17 @@ OpenGLRenderer::OpenGLRenderer() { // aui::sl_gen::line_solid_dashed::fsh::glsl120::Shader>(mLineSolidDashedShader); { - mRectangleVao.indicesByCount(BATCH_VERTEX_COUNT); + mRectangleVao.indicesByCount(BATCH_BUFFER_SIZE); } { - mRectangleVao.indicesByCount(BATCH_VERTEX_COUNT); + mRectangleVao.indicesByCount(BATCH_BUFFER_SIZE); } - mBatchVertices.fill(glm::vec3{0}); + mBatchVertices.fill(0.f); mCurrentBatchVertex = mBatchVertices.begin(); } void OpenGLRenderer::handleCmds(std::vector cmds) { - auto getBrushIndex = [](Cmd& cmd) { + auto getBrushId = [](Cmd& cmd) { unsigned char result; const char OFFSET = 3; @@ -294,8 +299,7 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { return result; }; - // TODO: Look into using z index as a batch key component to reduce overdraw - auto getZIndex = [](Cmd& cmd) -> uint16_t { + auto getZIndex = [](Cmd& cmd) -> int16_t { std::optional result; std::visit(aui::lambda_overloaded { @@ -306,33 +310,41 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { } }, cmd.arg); - return static_cast(result.value_or(999)); + return static_cast(result.value_or(std::numeric_limits::max())); }; for (auto& cmd : cmds) { cmd.batchId = { + .brushId = getBrushId(cmd), .cmdId = static_cast(cmd.arg.index()), - .brushId = getBrushIndex(cmd), + .zIndex = getZIndex(cmd), }; } std::ranges::sort(cmds, [](const Cmd& cmdA, const Cmd& cmdB) { - return cmdA.batchId.value < cmdB.batchId.value; + return cmdA.batchId.value > cmdB.batchId.value; }); + // Defining references to required members to avoid passing this as upvalue auto &rectangleVao = mRectangleVao; - auto &batchVerticies = mBatchVertices; + auto &batchVertices = mBatchVertices; + auto &batchShader = mBatchShader; + auto ¤tBatchVertex = mCurrentBatchVertex; auto drawBatch = [&](const char *name) { - rectangleVao.insert(0, std::span{batchVerticies}, name); - rectangleVao.drawElements(); + if (batchShader == nullptr or currentBatchVertex == batchVertices.begin()) + return; + + batchShader->use(); + rectangleVao.insert(0, std::span{batchVertices}, name); // TODO: move this and make it more expandable glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 7, 0); + const size_t stride = sizeof(glm::vec4) * 2; + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, stride, 0); glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 7, reinterpret_cast(3 * sizeof(float))); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, stride, reinterpret_cast(sizeof(glm::vec4))); + rectangleVao.drawElements(); }; BatchId_t currentBatchId = 0; bool breakBatch = false; - auto ¤tBatchVertex = mCurrentBatchVertex; auto dispatch = [&](Cmd& cmd) { BatchId_t nextId = cmd.batchId.value + 1; // + 1 so 0 ID cmd 0 ID brush != NULL if (!currentBatchId) { @@ -349,9 +361,9 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { return; drawBatch("Batch"); currentBatchId = nextId; - std::ranges::fill(batchVerticies, glm::vec3(0)); - currentBatchVertex = batchVerticies.begin(); - breakBatch = false; + std::ranges::fill(batchVertices, 0.f); + currentBatchVertex = batchVertices.begin(); + breakBatch = false; }; for (auto& cmd : cmds) { @@ -400,9 +412,7 @@ std::array OpenGLRenderer::getVerticesForRect(glm::vec2 position, }; } -void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const int zIndex) { - appendRect(position, size, zIndex, cmd.transform); - +void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const zIndex_t zIndex) { std::visit(aui::lambda_overloaded{ [&](const ALinearGradientBrush& brush) { // gradientBrush(cmd, brush, *this, *mGradientShader); @@ -411,37 +421,13 @@ void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::v // texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); }, [&](const ASolidBrush& brush) { - solidBrush(cmd, brush, *this, *mSolidShader); + ASolidBrush::Data data = solidBrush(cmd, brush, *this, *mSolidShader); + appendRect(position, size, zIndex, cmd.transform, data); }, [](const ACustomShaderBrush& ) {}, }, brush); } -void OpenGLRenderer::appendColor(const AColor color) { - *mCurrentBatchVertex++ = glm::vec4(color); -} - -static constexpr size_t Z_DEPTH = 1000; -void OpenGLRenderer::appendRect(const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform) { - float x = position.x; - float y = position.y; - float w = x + size.x; - float h = y + size.y; - float z = -1.f + zIndex * (1. / Z_DEPTH); - - std::array verticies { - glm::vec3 { x, h, z }, - glm::vec3 { w, h, z }, - glm::vec3 { x, y, z }, - glm::vec3 { w, y, z }, - }; - - for (const auto& vertex : verticies) { - glm::vec4 vertexTransformed = transform * glm::vec4(vertex, 1.0f); - *mCurrentBatchVertex++ = glm::vec3(vertexTransformed); - } -} - void OpenGLRenderer::identityUv() { const glm::vec2 uvs[] = { {0, 1}, @@ -456,7 +442,7 @@ void OpenGLRenderer::renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, - const int zIndex) { + const zIndex_t zIndex) { std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mRoundedGradientShader); }, @@ -467,14 +453,14 @@ void OpenGLRenderer::renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, identityUv(); gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_SIZE, 2.f * radius / size); - appendRect(position, size, zIndex, cmd.transform); + // appendRect(position, size, zIndex, cmd.transform); } void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float lineWidth, - const int zIndex) { + const zIndex_t zIndex) { std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, @@ -515,7 +501,7 @@ void OpenGLRenderer::renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& glm::vec2 size, float radius, int borderWidth, - const int zIndex) { + const zIndex_t zIndex) { std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, @@ -531,14 +517,14 @@ void OpenGLRenderer::renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_SIZE, 2.f * radius / size); gl::Program::currentShader()->set(aui::ShaderUniforms::INNER_SIZE, 2.f * (radius - borderWidth) / innerSize); gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_TO_INNER, size / innerSize); - appendRect(position, size, zIndex, cmd.transform); + // appendRect(position, size, zIndex, cmd.transform); } void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, glm::vec2 size, float blurRadius, const AColor& color, - const int zIndex) { + const zIndex_t zIndex) { AUI_ASSERTX(blurRadius >= 0.f, "blurRadius is expected to be non negative, use boxShadowInner for inset shadows instead"); identityUv(); @@ -578,7 +564,7 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, float borderRadius, const AColor& color, glm::vec2 offset, - const int zIndex) { + const zIndex_t zIndex) { AUI_ASSERTX(blurRadius >= 0.f, "blurRadius is expected to be non negative"); blurRadius *= -1.f; identityUv(); @@ -605,7 +591,7 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, // }; // mRectangleVao.insert(0, std::span{uvs}, "boxShadowInner"); - appendRect(glm::vec2{x, y}, glm::vec2{w, h}, zIndex, cmd.transform); + // appendRect(glm::vec2{x, y}, glm::vec2{w, h}, zIndex, cmd.transform); } void OpenGLRenderer::renderString(const Cmd& cmd, glm::vec2 position, @@ -704,7 +690,7 @@ class OpenGLPrerenderedString : public IRenderer::IPrerenderedString { if (AWindow::current()->profiling()->showBaseline) { mRenderer->rectangle( - ASolidBrush { AColor::RED.transparentize(0.5f) }, { 0, 0 }, { mTextWidth, 1 }); // debug baseline + ASolidBrush { AColor::RED.transparentize(0.5f) }, { 0, 0 }, std::numeric_limits::max(), { mTextWidth, 1 }); // debug baseline } auto width = img->width(); @@ -1141,7 +1127,7 @@ void OpenGLRenderer::renderSquareSector(const Cmd& cmd, const ABrush& brush, gl::Program::currentShader()->set(aui::ShaderUniforms::M2, m2); // TODO: replace 0 with zIndex - appendRect(position, size, 0, cmd.transform); + // appendRect(position, size, 0, cmd.transform); } @@ -1164,11 +1150,10 @@ void OpenGLRenderer::beginPaint(glm::uvec2 windowSize) { glDisable(GL_CULL_FACE); glClearColor(0, 0, 0, 0); - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_LESS); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); setBlending(Blending::NORMAL); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); resetStencil(); } diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.h b/aui.views/src/AUI/GL/OpenGLRenderer.h index 32e7a5222..2ab85bfc0 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.h +++ b/aui.views/src/AUI/GL/OpenGLRenderer.h @@ -12,22 +12,23 @@ #pragma once -#include +#include #include #include "AUI/GL/Program.h" #include "AUI/GL/Framebuffer.h" #include "AUI/GL/Vao.h" #include "AUI/Render/ABorderStyle.h" #include "AUI/GL/RenderTarget/TextureRenderTarget.h" +#include "AUI/Render/ABrush.h" #include "IBatchingRenderer.h" +#include "glm/detail/qualifier.hpp" #include "glm/fwd.hpp" +#include "glm/gtc/type_ptr.hpp" class OpenGLRenderer final: public IBatchingRenderer { friend class OpenGLPrerenderedString; friend class OpenGLMultiStringCanvas; public: - // TODO: Make this private, figure out how this should be accesible in brushes - void appendColor(const AColor color); struct FontEntryData: aui::noncopyable { Util::SimpleTexturePacker texturePacker; gl::Texture2D texture; @@ -70,13 +71,13 @@ friend class OpenGLMultiStringCanvas; AOptional mSymbolShaderSubPixel; AOptional mSquareSectorShader; AOptional mLineSolidDashedShader; - static constexpr size_t MAX_BATCH_ELEMENTS = 1000; - static constexpr size_t BATCH_VERTEX_COUNT = MAX_BATCH_ELEMENTS * 4; - std::array mBatchVertices; - std::array::iterator mCurrentBatchVertex; + static constexpr size_t BATCH_BUFFER_SIZE = 20000; + std::array mBatchVertices; + std::array::iterator mCurrentBatchVertex; gl::Vao mRectangleVao; gl::Vao mBorderVao; gl::Texture2D mGradientTexture; + gl::Program* mBatchShader; struct CharacterData { @@ -135,17 +136,45 @@ friend class OpenGLMultiStringCanvas; */ FramebufferFromPool getFramebufferForMultiPassEffect(glm::uvec2 minRequiredSize); - void appendRect(const glm::vec2 position, const glm::vec2 size, const int zIndex, const glm::mat4 transform); + static constexpr size_t Z_DEPTH = 1000; + template + void appendRect(const glm::vec2 position, const glm::vec2 size, const zIndex_t zIndex, const glm::mat4 transform, glm::vecadditionalData) { + float x = position.x; + float y = position.y; + float w = x + size.x; + float h = y + size.y; + float z = -1.f + zIndex * (1. / Z_DEPTH); + + std::array verticies { + glm::vec3 { x, h, z }, + glm::vec3 { w, h, z }, + glm::vec3 { x, y, z }, + glm::vec3 { w, y, z }, + }; + + for (const auto& vertex : verticies) { + glm::vec4 vertexTransformed = transform * glm::vec4(vertex, 1.0f); + appendVertexData(vertexTransformed); + appendVertexData(additionalData); + } + } + + template + void appendVertexData(glm::vec data) { + std::memcpy(mCurrentBatchVertex, glm::value_ptr(data), sizeof(float) * L); + mCurrentBatchVertex += L; + } + ASolidBrush::Data solidBrush(const IBatchingRenderer::Cmd& cmd, const ASolidBrush& brush, OpenGLRenderer& renderer, gl::Program& shader); private: // Helper methods that perform the actual rendering for each command. - void renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const int zIndex); - void renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, const int zIndex); - void renderRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float lineWidth, const int zIndex); - void renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, int borderWidth, const int zIndex); - void renderBoxShadow(const Cmd& cmd, glm::vec2 position, glm::vec2 size, float blurRadius, const AColor& color, const int zIndex); - void renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, glm::vec2 size, float blurRadius, float spreadRadius, float borderRadius, const AColor& color, glm::vec2 offset, const int zIndex); + void renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const zIndex_t zIndex); + void renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, const zIndex_t zIndex); + void renderRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float lineWidth, const zIndex_t zIndex); + void renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, int borderWidth, const zIndex_t zIndex); + void renderBoxShadow(const Cmd& cmd, glm::vec2 position, glm::vec2 size, float blurRadius, const AColor& color, const zIndex_t zIndex); + void renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, glm::vec2 size, float blurRadius, float spreadRadius, float borderRadius, const AColor& color, glm::vec2 offset, const zIndex_t zIndex); void renderString(const Cmd& cmd, glm::vec2 position, const AString& string, const AFontStyle& fs); void renderLines(const Cmd& cmd, const ABrush& brush, AArrayView points, const ABorderStyle& style, AMetric width); void renderLines(const Cmd& cmd, const ABrush& brush, AArrayView> points, const ABorderStyle& style, AMetric width); diff --git a/aui.views/src/AUI/Image/AAnimatedDrawable.cpp b/aui.views/src/AUI/Image/AAnimatedDrawable.cpp index 0404b9bcb..eedc2600a 100644 --- a/aui.views/src/AUI/Image/AAnimatedDrawable.cpp +++ b/aui.views/src/AUI/Image/AAnimatedDrawable.cpp @@ -42,7 +42,8 @@ void AAnimatedDrawable::draw(IRenderer& render, const IDrawable::Params& params) params.cropUvTopLeft, params.cropUvBottomRight, params.imageRendering, - }, params.offset, params.size); + // TODO: use actual z index here + }, params.offset, 0, params.size); } glm::ivec2 AAnimatedDrawable::getSizeHint() { diff --git a/aui.views/src/AUI/Image/SvgDrawable.cpp b/aui.views/src/AUI/Image/SvgDrawable.cpp index a66d2b970..db21e5280 100644 --- a/aui.views/src/AUI/Image/SvgDrawable.cpp +++ b/aui.views/src/AUI/Image/SvgDrawable.cpp @@ -53,6 +53,8 @@ void AVectorDrawable::draw(IRenderer& render, const IDrawable::Params& params) { .repeat = params.repeat, }, params.offset, + // TODO: replace with actual zindex + 0, size); }; for (auto& p : mRasterized) { diff --git a/aui.views/src/AUI/Render/ABrush.h b/aui.views/src/AUI/Render/ABrush.h index 9716c1021..129774830 100644 --- a/aui.views/src/AUI/Render/ABrush.h +++ b/aui.views/src/AUI/Render/ABrush.h @@ -24,6 +24,7 @@ #include "AUI/Enum/ImageRendering.h" #include "AUI/Util/AAngleRadians.h" #include "AUI/Traits/values.h" +#include "glm/fwd.hpp" /** @@ -31,6 +32,7 @@ */ struct ASolidBrush { AColor solidColor = AColor::WHITE; + using Data = glm::vec4; }; diff --git a/aui.views/src/AUI/Render/ARenderContext.h b/aui.views/src/AUI/Render/ARenderContext.h index 23df671b4..6ab36ce27 100644 --- a/aui.views/src/AUI/Render/ARenderContext.h +++ b/aui.views/src/AUI/Render/ARenderContext.h @@ -29,7 +29,7 @@ class IRenderer; * View containers are also responsible to skip rendering of views that are outside of the clipping. * * ARenderContext is useful only for container views. - * + * * ARenderContext passed to the view (possibly AViewContainer) describes an axis aligned bounding box relative * to it's coordinate space (position). * diff --git a/aui.views/src/AUI/Render/IRenderer.cpp b/aui.views/src/AUI/Render/IRenderer.cpp index 6f5962e8f..234e55bc4 100644 --- a/aui.views/src/AUI/Render/IRenderer.cpp +++ b/aui.views/src/AUI/Render/IRenderer.cpp @@ -9,10 +9,11 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include #include #include "IRenderer.h" -void IRenderer::stub(glm::vec2 position, glm::vec2 size) { rectangle(ASolidBrush { 0xa0a0a0_rgb }, { 0, 0 }, size); } +void IRenderer::stub(glm::vec2 position, glm::vec2 size) { rectangle(ASolidBrush { 0xa0a0a0_rgb }, { 0, 0 }, std::numeric_limits::max(), size); } void IRenderer::backdrops(glm::ivec2 position, glm::ivec2 size, std::span backdrops) { stub(position, size); diff --git a/aui.views/src/AUI/Render/IRenderer.h b/aui.views/src/AUI/Render/IRenderer.h index 475f55073..fee266d20 100644 --- a/aui.views/src/AUI/Render/IRenderer.h +++ b/aui.views/src/AUI/Render/IRenderer.h @@ -30,8 +30,6 @@ class AColor; class AWindowBase; - - /** * Blending mode. *

Terminology used in this documentation:

@@ -255,6 +253,7 @@ class IRenderer: public aui::noncopyable { */ virtual void rectangle(const ABrush& brush, glm::vec2 position, + zIndex_t zIndex, glm::vec2 size) = 0; @@ -267,6 +266,7 @@ class IRenderer: public aui::noncopyable { */ virtual void roundedRectangle(const ABrush& brush, glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float radius) = 0; @@ -279,6 +279,7 @@ class IRenderer: public aui::noncopyable { */ virtual void rectangleBorder(const ABrush& brush, glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float lineWidth = 1.f) = 0; /** @@ -291,6 +292,7 @@ class IRenderer: public aui::noncopyable { */ virtual void roundedRectangleBorder(const ABrush& brush, glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float radius, int borderWidth) = 0; @@ -304,6 +306,7 @@ class IRenderer: public aui::noncopyable { * @param color shadow color */ virtual void boxShadow(glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float blurRadius, const AColor& color) = 0; @@ -320,6 +323,7 @@ class IRenderer: public aui::noncopyable { * of a simple rectangle position offset. */ virtual void boxShadowInner(glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float blurRadius, float spreadRadius, @@ -425,7 +429,7 @@ class IRenderer: public aui::noncopyable { const glm::vec2& size, AAngleRadians begin, AAngleRadians end) = 0; - + /** * @brief Sets the color which is multiplied with any brush. * @param color color diff --git a/aui.views/src/AUI/Software/SoftwareRenderer.cpp b/aui.views/src/AUI/Software/SoftwareRenderer.cpp index f15a4c78c..a43d43d56 100644 --- a/aui.views/src/AUI/Software/SoftwareRenderer.cpp +++ b/aui.views/src/AUI/Software/SoftwareRenderer.cpp @@ -181,6 +181,7 @@ glm::mat4 SoftwareRenderer::getProjectionMatrix() const { void SoftwareRenderer::rectangle(const ABrush& brush, glm::vec2 position, + zIndex_t zIndex, glm::vec2 size) { auto transformedPosition = glm::ivec2(mTransform * glm::vec4(position, 1.f, 1.f)); auto end = transformedPosition + glm::ivec2(size); @@ -198,6 +199,7 @@ void SoftwareRenderer::rectangle(const ABrush& brush, void SoftwareRenderer::roundedRectangle(const ABrush& brush, glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float radius) { RoundedRect r(int(radius), glm::ivec2(size), glm::ivec2(mTransform * glm::vec4(position, 1.f, 1.f))); @@ -222,16 +224,18 @@ void SoftwareRenderer::roundedRectangle(const ABrush& brush, void SoftwareRenderer::rectangleBorder(const ABrush& brush, glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float lineWidth) { - rectangle(brush, position, {size.x, lineWidth}); - rectangle(brush, position + glm::vec2{0, size.y - lineWidth}, {size.x, lineWidth}); - rectangle(brush, position + glm::vec2{0, lineWidth}, {lineWidth, size.y - 2 * lineWidth}); - rectangle(brush, position + glm::vec2{size.x - lineWidth, lineWidth}, {lineWidth, size.y - 2 * lineWidth}); + rectangle(brush, position, 0, {size.x, lineWidth}); + rectangle(brush, position + glm::vec2{0, size.y - lineWidth}, 0, {size.x, lineWidth}); + rectangle(brush, position + glm::vec2{0, lineWidth}, 0, {lineWidth, size.y - 2 * lineWidth}); + rectangle(brush, position + glm::vec2{size.x - lineWidth, lineWidth}, 0, {lineWidth, size.y - 2 * lineWidth}); } void SoftwareRenderer::roundedRectangleBorder(const ABrush& brush, glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float radius, int borderWidth) { @@ -268,6 +272,7 @@ void SoftwareRenderer::roundedRectangleBorder(const ABrush& brush, } void SoftwareRenderer::boxShadow(glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float blurRadius, const AColor& color) { @@ -287,7 +292,7 @@ void SoftwareRenderer::boxShadow(glm::vec2 position, .sigma = blurRadius / 2.f, }; - for (int y = 0; y < iSize.y; ++y) { + for (int y = 0; y < iSize.y; ++y) { for (int x = 0; x < iSize.x; ++x) { const auto result = Shader::entry(Shader::Inter { .vertex = glm::ivec4(iTransformedPos + glm::ivec2{x, y}, 0, 1), @@ -303,6 +308,7 @@ void SoftwareRenderer::boxShadow(glm::vec2 position, } } void SoftwareRenderer::boxShadowInner(glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float blurRadius, float spreadRadius, @@ -325,7 +331,7 @@ void SoftwareRenderer::boxShadowInner(glm::vec2 position, .sigma = blurRadius / 2.f, }; - for (int y = 0; y < iSize.y; ++y) { + for (int y = 0; y < iSize.y; ++y) { for (int x = 0; x < iSize.x; ++x) { const auto result = Shader::entry(Shader::Inter { .vertex = glm::vec4(transformedPos + glm::vec2{x, y}, 0.f, 1.f), @@ -401,7 +407,7 @@ class SoftwarePrerenderedString: public IRenderer::IPrerenderedString { for (int y = 0; y < size.y; ++y) { for (int x = 0; x < size.x; ++x) { auto color = entry.image->get({x, y}); - + mRenderer->putPixel(transformedPosition + glm::ivec2{ x, y }, AColor{ color.r, color.g, color.b, color.a * finalColor.a }, Blending::INVERSE_SRC); mRenderer->putPixel(transformedPosition + glm::ivec2{ x, y }, color * finalColor, Blending::ADDITIVE); } @@ -565,7 +571,7 @@ void SoftwareRenderer::drawLine(const ABrush& brush, glm::vec2 p1, glm::vec2 p2, // TODO if (p1.x == p2.x || p1.y == p2.y) { auto begin = glm::min(p1, p2); - rectangle(brush, begin, glm::max(p1, p2) - begin + glm::vec2(1)); + rectangle(brush, begin, 0, glm::max(p1, p2) - begin + glm::vec2(1)); return; } } diff --git a/aui.views/src/AUI/Software/SoftwareRenderer.h b/aui.views/src/AUI/Software/SoftwareRenderer.h index d0bf81f32..7e4383a16 100644 --- a/aui.views/src/AUI/Software/SoftwareRenderer.h +++ b/aui.views/src/AUI/Software/SoftwareRenderer.h @@ -107,30 +107,36 @@ class API_AUI_VIEWS SoftwareRenderer: public IRenderer { void rectangle(const ABrush& brush, glm::vec2 position, + zIndex_t zIndex, glm::vec2 size) override; void roundedRectangle(const ABrush& brush, glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float radius) override; void rectangleBorder(const ABrush& brush, glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float lineWidth) override; void roundedRectangleBorder(const ABrush& brush, glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float radius, int borderWidth) override; void boxShadow(glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float blurRadius, const AColor& color) override; - + void boxShadowInner(glm::vec2 position, + zIndex_t zIndex, glm::vec2 size, float blurRadius, float spreadRadius, diff --git a/aui.views/src/AUI/Util/ACursorSelectable.h b/aui.views/src/AUI/Util/ACursorSelectable.h index 481272ed8..7ab32a6d7 100644 --- a/aui.views/src/AUI/Util/ACursorSelectable.h +++ b/aui.views/src/AUI/Util/ACursorSelectable.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -139,7 +140,7 @@ class API_AUI_VIEWS ACursorSelectable { auto drawRects = [&] { for (auto r : rects) { - render.rectangle(ASolidBrush{}, r.p1, r.size()); + render.rectangle(ASolidBrush{}, r.p1, std::numeric_limits::max(), r.size()); } }; { diff --git a/aui.views/src/AUI/Util/ANoiseDrawable.cpp b/aui.views/src/AUI/Util/ANoiseDrawable.cpp index a9af5dacf..c27bbd7f4 100644 --- a/aui.views/src/AUI/Util/ANoiseDrawable.cpp +++ b/aui.views/src/AUI/Util/ANoiseDrawable.cpp @@ -33,7 +33,8 @@ void ANoiseDrawable::draw(IRenderer& render, const IDrawable::Params& params) { .uv2 = glm::vec2(params.size) * glm::vec2(0.37390528174893522421f, 0.37577434667f), .imageRendering = ImageRendering::SMOOTH, .repeat = Repeat::X_Y, - }, params.offset, params.size); + // TODO: use actual z index here + }, params.offset, 0, params.size); } glm::ivec2 ANoiseDrawable::getSizeHint() { return {1, 1}; } diff --git a/aui.views/src/AUI/Util/AStubWindowManager.h b/aui.views/src/AUI/Util/AStubWindowManager.h index 30335da0e..24466b8a5 100644 --- a/aui.views/src/AUI/Util/AStubWindowManager.h +++ b/aui.views/src/AUI/Util/AStubWindowManager.h @@ -40,7 +40,7 @@ class API_AUI_VIEWS AStubWindowManager: public AWindowManager { /** * @brief Renderer used for window manager. */ - _unique renderer = std::make_unique(); + _unique renderer = std::make_unique(); }; static void setConfig(Config config); diff --git a/aui.views/src/AUI/Util/AViewProfiler.cpp b/aui.views/src/AUI/Util/AViewProfiler.cpp index 6d0e277c7..2f2f7da16 100644 --- a/aui.views/src/AUI/Util/AViewProfiler.cpp +++ b/aui.views/src/AUI/Util/AViewProfiler.cpp @@ -33,6 +33,7 @@ void AViewProfiler::displayBoundsOn(AView& v, ARenderContext ctx) { { ctx.render.rectangle(ASolidBrush{0x7cb6c180u}, {v.getPadding().left, v.getPadding().top}, + v.getZIndex(), {v.getWidth() - v.getPadding().horizontal(), v.getHeight() - v.getPadding().vertical()}); } @@ -40,6 +41,7 @@ void AViewProfiler::displayBoundsOn(AView& v, ARenderContext ctx) { { ctx.render.rectangle(ASolidBrush{0xbccf9180u}, {0, 0}, + v.getZIndex(), v.getSize()); } @@ -47,6 +49,7 @@ void AViewProfiler::displayBoundsOn(AView& v, ARenderContext ctx) { { ctx.render.rectangle(ASolidBrush{0xffcca4a0u}, {-v.getMargin().left, -v.getMargin().top}, + v.getZIndex(), {v.getWidth() + v.getMargin().horizontal(), v.getHeight() + v.getMargin().vertical()}); } @@ -69,6 +72,7 @@ void AViewProfiler::displayBoundsOn(AView& v, ARenderContext ctx) { { ctx.render.rectangle(ASolidBrush{0x00000070u}, {x, y}, + v.getZIndex(), {s->getWidth() + 4_dp, fs.size * 2.5 + 2_dp}); } s->draw(); diff --git a/aui.views/src/AUI/Util/ImageDrawable.cpp b/aui.views/src/AUI/Util/ImageDrawable.cpp index 3a9eb0749..13513808e 100644 --- a/aui.views/src/AUI/Util/ImageDrawable.cpp +++ b/aui.views/src/AUI/Util/ImageDrawable.cpp @@ -47,7 +47,8 @@ void AImageDrawable::draw(IRenderer& render, const IDrawable::Params& params) { .uv2 = params.cropUvBottomRight, .imageRendering = params.imageRendering, .repeat = params.repeat, - }, params.offset, params.size); + // TODO: use actual z index here + }, params.offset, 0, params.size); } AImage AImageDrawable::rasterize(glm::ivec2 imageSize) { diff --git a/aui.views/src/AUI/View/AAbstractTypeable.cpp b/aui.views/src/AUI/View/AAbstractTypeable.cpp index 9cc17670b..a8a244b1f 100644 --- a/aui.views/src/AUI/View/AAbstractTypeable.cpp +++ b/aui.views/src/AUI/View/AAbstractTypeable.cpp @@ -310,7 +310,8 @@ void AAbstractTypeable::drawCursorImpl(IRenderer& renderer, glm::ivec2 position, } renderer.setBlending(Blending::INVERSE_DST); AUI_DEFER { renderer.setBlending(Blending::NORMAL); }; - renderer.rectangle(ASolidBrush{}, position, {1, lineHeight}); + // TODO: use actual z index here + renderer.rectangle(ASolidBrush{}, position, 0, {1, lineHeight}); } void AAbstractTypeable::moveCursorLeft() { diff --git a/aui.views/src/AUI/View/AGroupBox.cpp b/aui.views/src/AUI/View/AGroupBox.cpp index 22cf92f08..c17f4bfa7 100644 --- a/aui.views/src/AUI/View/AGroupBox.cpp +++ b/aui.views/src/AUI/View/AGroupBox.cpp @@ -35,6 +35,7 @@ namespace { AUI_REPEAT(2) { // render twice to definitely avoid stencil issues ctx.render.rectangle(ASolidBrush{}, d, + mZIndex, mTitle->getSize()); } } diff --git a/aui.views/src/AUI/View/ARulerArea.cpp b/aui.views/src/AUI/View/ARulerArea.cpp index 4e6fc8e98..ca8fa06f5 100644 --- a/aui.views/src/AUI/View/ARulerArea.cpp +++ b/aui.views/src/AUI/View/ARulerArea.cpp @@ -20,6 +20,7 @@ #include "AScrollbar.h" #include #include +#include using namespace ass; using namespace declarative; @@ -105,9 +106,11 @@ void ARulerArea::render(ARenderContext ctx) { ctx.render.setBlending(Blending::INVERSE_DST); ctx.render.rectangle(ASolidBrush{}, {mMousePos.x, 0.f}, + std::numeric_limits::max(), {1, mMousePos.y}); ctx.render.rectangle(ASolidBrush{}, {0.f, mMousePos.y}, + std::numeric_limits::max(), {mMousePos.x, 1}); diff --git a/aui.views/src/AUI/View/ARulerView.cpp b/aui.views/src/AUI/View/ARulerView.cpp index 9cdfdeffc..b5f9fef7c 100644 --- a/aui.views/src/AUI/View/ARulerView.cpp +++ b/aui.views/src/AUI/View/ARulerView.cpp @@ -59,11 +59,13 @@ void ARulerView::render(ARenderContext ctx) { // large dashes ctx.render.rectangle(ASolidBrush{}, {mOffsetPx + operator ""_dp(i * delayLarge), 0.f}, + mZIndex, {1, totalHeight}); // medium dashes ctx.render.rectangle(ASolidBrush{}, {mOffsetPx + operator ""_dp(i * delayLarge + delayMedium), totalHeight / 2}, + mZIndex, {1, totalHeight / 2}); @@ -72,12 +74,14 @@ void ARulerView::render(ARenderContext ctx) { int smallDashOffset = j * delaySmall; ctx.render.rectangle(ASolidBrush{}, {mOffsetPx + operator ""_dp(i * delayLarge + smallDashOffset), - 3 * totalHeight / 4}, + 3 * totalHeight / 4}, + mZIndex, {1, totalHeight / 4}); ctx.render.rectangle(ASolidBrush{}, {mOffsetPx + operator ""_dp(i * delayLarge + smallDashOffset + delayMedium), - 3 * totalHeight / 4}, + 3 * totalHeight / 4}, + mZIndex, {1, totalHeight / 4}); } } diff --git a/aui.views/src/AUI/View/AView.cpp b/aui.views/src/AUI/View/AView.cpp index 1c391ef52..8d1f4b5f9 100644 --- a/aui.views/src/AUI/View/AView.cpp +++ b/aui.views/src/AUI/View/AView.cpp @@ -105,12 +105,14 @@ void AView::drawStencilMask(ARenderContext ctx) if (mBorderRadius > 0) { ctx.render.roundedRectangle(ASolidBrush{}, {mPadding.left, mPadding.top}, + mZIndex, {getWidth() - mPadding.horizontal(), getHeight() - mPadding.vertical()}, glm::max(mBorderRadius - std::min(mPadding.horizontal(), mPadding.vertical()), 0.f)); } else { // TODO: figure out why this is rendered opaque when batching // ctx.render.rectangle(ASolidBrush{}, // {mPadding.left, mPadding.top}, + // mZIndex, // {getWidth() - mPadding.horizontal(), getHeight() - mPadding.vertical()}); } break; @@ -512,6 +514,12 @@ void AView::setPosition(glm::ivec2 position) { redraw(); emit mPositionChanged(position); } +void AView::setZIndex(zIndex_t zIndex) { + mSkipUntilLayoutUpdate = false; + mZIndex = zIndex; + redraw(); + emit mZIndexChanged(zIndex); +} void AView::setSize(glm::ivec2 size) { mMarkedMinContentSizeInvalid = false; diff --git a/aui.views/src/AUI/View/AView.h b/aui.views/src/AUI/View/AView.h index b2cf5a239..9c154e2fd 100644 --- a/aui.views/src/AUI/View/AView.h +++ b/aui.views/src/AUI/View/AView.h @@ -48,6 +48,7 @@ #include #include +using zIndex_t = int16_t; class AWindow; class AWindowBase; @@ -209,6 +210,12 @@ class API_AUI_VIEWS AView: public AObject return mPosition; } + [[nodiscard]] + zIndex_t getZIndex() const noexcept + { + return mZIndex; + } + /** * @brief The center point position of the view relatively to top left corner of the window. * @details @@ -585,6 +592,8 @@ class API_AUI_VIEWS AView: public AObject virtual void setPosition(glm::ivec2 position); + void setZIndex(zIndex_t zIndex); + /** * Set size ignoring all restrictions (i.e. min size, max size, fixed size, etc...). Used by AAnimator. * @param size @@ -1042,6 +1051,10 @@ class API_AUI_VIEWS AView: public AObject */ emits mPositionChanged; + zIndex_t mZIndex = 0; + + emits mZIndexChanged; + /** * @brief Size, including content area, border and padding. */ diff --git a/aui.views/src/AUI/View/AViewContainerBase.cpp b/aui.views/src/AUI/View/AViewContainerBase.cpp index bd1c82539..4eddf4b17 100644 --- a/aui.views/src/AUI/View/AViewContainerBase.cpp +++ b/aui.views/src/AUI/View/AViewContainerBase.cpp @@ -75,7 +75,7 @@ void AViewContainerBase::drawView(const _& view, ARenderContext contextOf if (showRedraw) [[unlikely]] { auto c = contextOfTheView.render.getColor(); AUI_DEFER { contextOfTheView.render.setColorForced(c); }; - contextOfTheView.render.rectangle(ASolidBrush{0x40ff00ff_argb}, view->getPosition(), view->getSize()); + contextOfTheView.render.rectangle(ASolidBrush{0x40ff00ff_argb}, view->getPosition(), view->getZIndex(), view->getSize()); } }; @@ -134,6 +134,7 @@ void AViewContainerBase::addViews(AVector<_> views) { } for (const auto& view: views) { view->mParent = this; + view->setZIndex(mZIndex + 1); view->mSkipUntilLayoutUpdate = true; AUI_NULLSAFE(mLayout)->addView(view); view->onViewGraphSubtreeChanged(); @@ -157,6 +158,7 @@ void AViewContainerBase::addView(const _& view) { view->mSkipUntilLayoutUpdate = true; mViews << view; view->mParent = this; + view->setZIndex(mZIndex + 1); AUI_NULLSAFE(mLayout)->addView(view); view->onViewGraphSubtreeChanged(); invalidateCaches(); @@ -170,6 +172,7 @@ void AViewContainerBase::addViewCustomLayout(const _& view) { } mViews << view; view->mParent = this; + view->setZIndex(mZIndex + 1); view->setSize(view->getMinimumSize()); view->mSkipUntilLayoutUpdate = true; AUI_NULLSAFE(mLayout)->addView(view); @@ -187,6 +190,7 @@ void AViewContainerBase::addView(size_t index, const _& view) { mViews.insert(mViews.begin() + index, view); view->mParent = this; AUI_NULLSAFE(mLayout)->addView(view, index); + view->setZIndex(mZIndex + 1); view->onViewGraphSubtreeChanged(); invalidateCaches(); emit childrenChanged; @@ -213,6 +217,7 @@ void AViewContainerBase::setLayoutImpl(_unique layout, std::unique_lock mViews = mLayout->getAllViews(); for (const auto& v : mViews) { v->mParent = this; + v->setZIndex(mZIndex + 1); v->onViewGraphSubtreeChanged(); } } diff --git a/examples/7guis/circle_drawer/src/main.cpp b/examples/7guis/circle_drawer/src/main.cpp index 34cf9341d..817345e23 100644 --- a/examples/7guis/circle_drawer/src/main.cpp +++ b/examples/7guis/circle_drawer/src/main.cpp @@ -94,11 +94,11 @@ class CircleDrawArea : public AView { for (const auto& circle : *mState->circles) { if (&circle == mHoveredCircle) { ctx.render.roundedRectangle( - ASolidBrush { AColor::GRAY }, circle.position - *circle.radius, glm::vec2(circle.radius * 2.f), + ASolidBrush { AColor::GRAY }, circle.position - *circle.radius, mZIndex, glm::vec2(circle.radius * 2.f), circle.radius); } ctx.render.roundedRectangleBorder( - ASolidBrush { AColor::BLACK }, circle.position - *circle.radius, glm::vec2(circle.radius * 2.f), + ASolidBrush { AColor::BLACK }, circle.position - *circle.radius, mZIndex, glm::vec2(circle.radius * 2.f), circle.radius, 1); } } @@ -233,4 +233,4 @@ class CircleDrawerWindow : public AWindow { AUI_ENTRY { _new()->show(); return 0; -} \ No newline at end of file +} diff --git a/examples/app/fractal/src/FractalView.cpp b/examples/app/fractal/src/FractalView.cpp index bc906a376..25915a586 100644 --- a/examples/app/fractal/src/FractalView.cpp +++ b/examples/app/fractal/src/FractalView.cpp @@ -88,7 +88,7 @@ void FractalView::render(ARenderContext context) { mShader.use(); mTexture->bind(); - context.render.rectangle(ACustomShaderBrush {}, { 0, 0 }, getSize()); + context.render.rectangle(ACustomShaderBrush {}, { 0, 0 }, mZIndex, getSize()); } void FractalView::setSize(glm::ivec2 size) { diff --git a/examples/app/game_of_life/src/main.cpp b/examples/app/game_of_life/src/main.cpp index 852c85498..d76b2abfe 100644 --- a/examples/app/game_of_life/src/main.cpp +++ b/examples/app/game_of_life/src/main.cpp @@ -128,7 +128,7 @@ class CellsView : public AView { void render(ARenderContext ctx) override { AView::render(ctx); if (mTexture) { - ctx.render.rectangle(ATexturedBrush { mTexture }, { 0, 0 }, float(SCALE) * glm::vec2(mCells->size())); + ctx.render.rectangle(ATexturedBrush { mTexture }, { 0, 0 }, mZIndex, float(SCALE) * glm::vec2(mCells->size())); } auto drawGrid = [&] { ASmallVector, 128 * 2> points; diff --git a/examples/ui/game_inventory/src/main.cpp b/examples/ui/game_inventory/src/main.cpp index 8f708bd26..86bb017c1 100644 --- a/examples/ui/game_inventory/src/main.cpp +++ b/examples/ui/game_inventory/src/main.cpp @@ -10,6 +10,7 @@ */ #include "AUI/ASS/Property/BackgroundSolid.h" +#include "AUI/ASS/Property/Margin.h" #include "AUI/Common/AColor.h" #include "AUI/Platform/ARenderingContextOptions.h" #include "AUI/View/AForEachUI.h" @@ -23,6 +24,7 @@ #include #include #include +#include using namespace ass; using namespace declarative; @@ -54,7 +56,7 @@ _ itemStackView(const _>>& itemStack) { AObject::connect( AUI_REACT(ass::PropertyListRecursive { // BackgroundImage { (*itemStack) ->hasValue() ? ":texture/item/{}.png"_format((**itemStack)->id) : "" }, - BackgroundSolid{ AColor{ 1.0, 1.0, 1.0}}, + BackgroundSolid{ AColor{ "#FB1816" }}, Expanding {}, }), AUI_SLOT(it)::setCustomStyle); @@ -133,6 +135,7 @@ AUI_ENTRY { inventoryGrid(state), } AUI_OVERRIDE_STYLE { Expanding {}, + BackgroundSolid{ AColor{ "#2F3F59" }}, }, } AUI_OVERRIDE_STYLE { Padding { {}, 64_dp } }); window->show(); From 53e21743c1474d0fbd236146a60ceee4b272b1db Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Sat, 21 Mar 2026 23:12:33 +0300 Subject: [PATCH 20/22] batching: transparency ordering fix --- aui.views/src/AUI/GL/IBatchingRenderer.h | 18 +++++++----------- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 13 ++++++------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/aui.views/src/AUI/GL/IBatchingRenderer.h b/aui.views/src/AUI/GL/IBatchingRenderer.h index 14605d1b7..a9906c627 100644 --- a/aui.views/src/AUI/GL/IBatchingRenderer.h +++ b/aui.views/src/AUI/GL/IBatchingRenderer.h @@ -93,18 +93,13 @@ class IBatchingRenderer : public IRenderer { AWindowBase* window; }; using BatchId_t = uint32_t; - union BatchId { + struct BatchId { BatchId_t value; - struct { - unsigned char brushId : 8; - unsigned char cmdId : 8; - zIndex_t zIndex : 16; - }; - // TODO: finish bit order fix - // static BatchId new(int16_t z, uint8_t cmd, uint8_t brush) { - // return { static_cast(z << 16) | static_cast(cmd << 8) | static_cast(brush) }; - // } - // auto operator<=>(const BatchId&) const = default; + BatchId() : value{std::numeric_limits::max()} {}; + BatchId(int16_t z, uint8_t cmd, uint8_t brush) { + value = static_cast(z) << 16 | static_cast(cmd << 8) | static_cast(brush); + } + auto operator<=>(const BatchId&) const = default; }; struct Cmd { glm::mat4 transform; @@ -149,6 +144,7 @@ class IBatchingRenderer : public IRenderer { .transform = getTransform(), .color = getColor(), .arg = std::move(arg), + .batchId = BatchId{} }); } diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index f4e1e2871..c19077918 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -310,20 +310,19 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { } }, cmd.arg); - return static_cast(result.value_or(std::numeric_limits::max())); + return result.value_or(std::numeric_limits::max()); }; for (auto& cmd : cmds) { - cmd.batchId = { - .brushId = getBrushId(cmd), - .cmdId = static_cast(cmd.arg.index()), - .zIndex = getZIndex(cmd), + cmd.batchId = BatchId { + getZIndex(cmd), + static_cast(cmd.arg.index()), + getBrushId(cmd) }; } - std::ranges::sort(cmds, [](const Cmd& cmdA, const Cmd& cmdB) { + std::ranges::stable_sort(cmds, [](const Cmd& cmdA, const Cmd& cmdB) { return cmdA.batchId.value > cmdB.batchId.value; }); - // Defining references to required members to avoid passing this as upvalue auto &rectangleVao = mRectangleVao; auto &batchVertices = mBatchVertices; auto &batchShader = mBatchShader; From 708b21f5b99e78d47293309f78bcef7283539936 Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Mon, 23 Mar 2026 13:58:48 +0300 Subject: [PATCH 21/22] batching: gradient WIP --- aui.views/CMakeLists.txt | 34 +-- aui.views/shaders/basic.vsh | 7 - aui.views/shaders/basic_gradient.vert | 23 ++ .../shaders/{basic.vert => basic_solid.vert} | 0 aui.views/shaders/gradient.frag | 13 ++ aui.views/shaders/gradient.sl | 11 - aui.views/shaders/gradient_textured.sl | 10 - aui.views/shaders/rect_gradient.fsh | 17 -- aui.views/shaders/rect_solid.fsh | 11 - aui.views/src/AUI/ASS/AStylesheet.cpp | 12 +- .../src/AUI/ASS/Property/BackgroundGradient.h | 9 +- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 206 ++++++++---------- aui.views/src/AUI/GL/OpenGLRenderer.h | 21 +- aui.views/src/AUI/GL/Program.cpp | 6 + aui.views/src/AUI/GL/Program.h | 5 + aui.views/src/AUI/Render/ABrush.h | 17 +- aui.views/src/AUI/Render/Brush/Gradient.h | 7 +- .../src/AUI/Software/SoftwareRenderer.cpp | 126 +++++------ aui.views/src/AUI/View/AView.cpp | 10 +- examples/ui/game_inventory/src/main.cpp | 3 +- 20 files changed, 261 insertions(+), 287 deletions(-) delete mode 100644 aui.views/shaders/basic.vsh create mode 100644 aui.views/shaders/basic_gradient.vert rename aui.views/shaders/{basic.vert => basic_solid.vert} (100%) create mode 100644 aui.views/shaders/gradient.frag delete mode 100644 aui.views/shaders/gradient.sl delete mode 100644 aui.views/shaders/gradient_textured.sl delete mode 100644 aui.views/shaders/rect_gradient.fsh delete mode 100644 aui.views/shaders/rect_solid.fsh diff --git a/aui.views/CMakeLists.txt b/aui.views/CMakeLists.txt index 310408c62..0a124463c 100644 --- a/aui.views/CMakeLists.txt +++ b/aui.views/CMakeLists.txt @@ -74,22 +74,22 @@ if (OPENGL_FOUND OR ANDROID OR IOS) aui_compile_assets(aui.views EXCLUDE uni/font/Roboto.ttf) endif () - auisl_shader(aui.views basic.vsh) - auisl_shader(aui.views basic_uv.vsh) - auisl_shader(aui.views shadow.fsh) - auisl_shader(aui.views shadow_inner.fsh) - auisl_shader(aui.views rect_solid.fsh) - auisl_shader(aui.views rect_solid_rounded.fsh) - auisl_shader(aui.views rect_textured.fsh) - auisl_shader(aui.views rect_unblend.fsh) - auisl_shader(aui.views rect_gradient.fsh) - auisl_shader(aui.views rect_gradient_rounded.fsh) - auisl_shader(aui.views border_rounded.fsh) - auisl_shader(aui.views symbol.vsh) - auisl_shader(aui.views symbol.fsh) - auisl_shader(aui.views symbol_sub.fsh) - auisl_shader(aui.views square_sector.fsh) - auisl_shader(aui.views line_solid_dashed.fsh) + # auisl_shader(aui.views basic.vsh) + # auisl_shader(aui.views basic_uv.vsh) + # auisl_shader(aui.views shadow.fsh) + # auisl_shader(aui.views shadow_inner.fsh) + # auisl_shader(aui.views rect_solid.fsh) + # auisl_shader(aui.views rect_solid_rounded.fsh) + # auisl_shader(aui.views rect_textured.fsh) + # auisl_shader(aui.views rect_unblend.fsh) + # auisl_shader(aui.views rect_gradient.fsh) + # auisl_shader(aui.views rect_gradient_rounded.fsh) + # auisl_shader(aui.views border_rounded.fsh) + # auisl_shader(aui.views symbol.vsh) + # auisl_shader(aui.views symbol.fsh) + # auisl_shader(aui.views symbol_sub.fsh) + # auisl_shader(aui.views square_sector.fsh) + # auisl_shader(aui.views line_solid_dashed.fsh) target_compile_definitions(aui.views PRIVATE $<$,$>:UNICODE=1> @@ -153,4 +153,4 @@ if (OPENGL_FOUND OR ANDROID OR IOS) endif () else () message("OpenGL library was not found. Disabling aui.views") -endif () \ No newline at end of file +endif () diff --git a/aui.views/shaders/basic.vsh b/aui.views/shaders/basic.vsh deleted file mode 100644 index 80d1dcdd6..000000000 --- a/aui.views/shaders/basic.vsh +++ /dev/null @@ -1,7 +0,0 @@ -input { - [0] vec3 pos -} - -entry { - sl_position = vec4(input.pos.xyz, 1) -} diff --git a/aui.views/shaders/basic_gradient.vert b/aui.views/shaders/basic_gradient.vert new file mode 100644 index 000000000..97aa03eed --- /dev/null +++ b/aui.views/shaders/basic_gradient.vert @@ -0,0 +1,23 @@ +#version 300 es + +precision highp float; + +layout(location = 0) in vec4 pos; +layout(location = 1) in vec4 color_start; +layout(location = 2) in vec4 color_end; +layout(location = 3) in float rotation; + +flat out vec4 vColorStart; +flat out vec4 vColorEnd; +out float vT; + +void main() { + gl_Position = pos; + + vec2 dir = vec2(cos(rotation), sin(rotation)); + + vT = dot(pos.xy, dir); + + vColorStart = color_start; + vColorEnd = color_end; +} diff --git a/aui.views/shaders/basic.vert b/aui.views/shaders/basic_solid.vert similarity index 100% rename from aui.views/shaders/basic.vert rename to aui.views/shaders/basic_solid.vert diff --git a/aui.views/shaders/gradient.frag b/aui.views/shaders/gradient.frag new file mode 100644 index 000000000..7a8954469 --- /dev/null +++ b/aui.views/shaders/gradient.frag @@ -0,0 +1,13 @@ +#version 300 es +precision highp float; + +flat in vec4 vColorStart; +flat in vec4 vColorEnd; +in float vT; + +out vec4 fragColor; + +void main() { + float t = clamp(vT * 0.5 + 0.5, 0.0, 1.0); + fragColor = mix(vColorStart, vColorEnd, t); +} diff --git a/aui.views/shaders/gradient.sl b/aui.views/shaders/gradient.sl deleted file mode 100644 index f0436fe59..000000000 --- a/aui.views/shaders/gradient.sl +++ /dev/null @@ -1,11 +0,0 @@ -uniform { - vec4 color1 - vec4 color2 - mat3 matUv -} - -vec4 gradient(vec2 uv) { - vec3 transformedUv = uniform.matUv * vec3(uv, 1) - vec4 c = mix(uniform.color1, uniform.color2, clamp(transformedUv.x, 0, 1)) - return c -} \ No newline at end of file diff --git a/aui.views/shaders/gradient_textured.sl b/aui.views/shaders/gradient_textured.sl deleted file mode 100644 index a83ff06f4..000000000 --- a/aui.views/shaders/gradient_textured.sl +++ /dev/null @@ -1,10 +0,0 @@ -uniform { - 2D gradientMap - mat3 matUv -} - -vec4 gradient(vec2 uv) { - vec3 transformedUv = uniform.matUv * vec3(uv, 1) - vec4 c = uniform.gradientMap[vec2(transformedUv.x, transformedUv.x)] - return c -} \ No newline at end of file diff --git a/aui.views/shaders/rect_gradient.fsh b/aui.views/shaders/rect_gradient.fsh deleted file mode 100644 index cbfaef451..000000000 --- a/aui.views/shaders/rect_gradient.fsh +++ /dev/null @@ -1,17 +0,0 @@ -import gradient - -inter { - vec2 uv -} - -uniform { - vec4 color -} - -output { - [0] vec4 albedo -} - -entry { - output.albedo = uniform.color * gradient(inter.uv) -} \ No newline at end of file diff --git a/aui.views/shaders/rect_solid.fsh b/aui.views/shaders/rect_solid.fsh deleted file mode 100644 index 3f438cb6c..000000000 --- a/aui.views/shaders/rect_solid.fsh +++ /dev/null @@ -1,11 +0,0 @@ -uniform { - vec4 color -} - -output { - [0] vec4 albedo -} - -entry { - output.albedo = uniform.color -} \ No newline at end of file diff --git a/aui.views/src/AUI/ASS/AStylesheet.cpp b/aui.views/src/AUI/ASS/AStylesheet.cpp index aa76bd60e..0ccff524c 100644 --- a/aui.views/src/AUI/ASS/AStylesheet.cpp +++ b/aui.views/src/AUI/ASS/AStylesheet.cpp @@ -144,10 +144,8 @@ AStylesheet::AStylesheet() { button::Default(t()), FontRendering::ANTIALIASING, BackgroundGradient { ALinearGradientBrush{ - .colors = { - {0.f, getOsThemeColorLighter()}, - {0.f, getOsThemeColor()}, - }, + .colorStart = getOsThemeColorLighter(), + .colorEnd = getOsThemeColor() } }, BoxShadow { 0, 1_dp, 3_dp, -1_dp, getOsThemeColor() }, Border { nullptr }, @@ -164,10 +162,8 @@ AStylesheet::AStylesheet() { { button::Default(t::hover()), BackgroundGradient { ALinearGradientBrush{ - .colors = { - {0.f, getOsThemeColorLighter()}, - {1.f, getOsThemeColor()}, - }, + .colorStart = getOsThemeColorLighter(), + .colorEnd = getOsThemeColor() } }, }, { diff --git a/aui.views/src/AUI/ASS/Property/BackgroundGradient.h b/aui.views/src/AUI/ASS/Property/BackgroundGradient.h index afac98fe3..6c1dfc6f9 100644 --- a/aui.views/src/AUI/ASS/Property/BackgroundGradient.h +++ b/aui.views/src/AUI/ASS/Property/BackgroundGradient.h @@ -17,6 +17,7 @@ #include #include "IProperty.h" +#include namespace ass { /** @@ -30,10 +31,8 @@ namespace ass { BackgroundGradient(ALinearGradientBrush brush) noexcept: gradient(std::move(brush)) {} BackgroundGradient(AColor begin, AColor end, AAngleRadians angle) noexcept: gradient(ALinearGradientBrush{ - .colors = { - {0.f, begin}, - {1.f, end}, - }, + .colorStart = begin, + .colorEnd = end, .rotation = angle }) {} BackgroundGradient(AColor begin, AColor end, ALayoutDirection direction) noexcept: BackgroundGradient(begin, end, direction == ALayoutDirection::VERTICAL ? 180_deg : 90_deg) {} @@ -62,4 +61,4 @@ namespace ass { }; } -} \ No newline at end of file +} diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index c19077918..64e9acf19 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -51,22 +51,6 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include #include @@ -105,28 +89,6 @@ static constexpr auto UV_BIAS = 0.001f; namespace { -void gradientBrush(const IBatchingRenderer::Cmd& cmd, const ALinearGradientBrush& brush, OpenGLRenderer& renderer, gl::Program& shader) { - shader.use(); - shader.set(aui::ShaderUniforms::COLOR, cmd.color); - aui::render::brush::gradient::Helper h(brush); - shader.set(aui::ShaderUniforms::GRADIENT_MAT_UV, h.matrix); - - if (h.colors.size() == 2) { - // simple gradient can be used - shader.set(aui::ShaderUniforms::COLOR1, glm::vec4(h.colors[0]) / 255.f); - shader.set(aui::ShaderUniforms::COLOR2, glm::vec4(h.colors[1]) / 255.f); - } else { - // complex gradient needs a texture - // tex.tex2D(h.gradientMap()); - - // TODO complex shader is broken, use simple shader instead with first and last color - shader.set(aui::ShaderUniforms::COLOR1, glm::vec4(h.colors.first()) / 255.f); - shader.set(aui::ShaderUniforms::COLOR2, glm::vec4(h.colors.last()) / 255.f); - } - - renderer.identityUv(); -} - void texturedBrush(const IBatchingRenderer::Cmd& cmd, const ATexturedBrush& brush, OpenGLRenderer& renderer, gl::Program& shader, gl::Vao& tempVao) { shader.use(); shader.set(aui::ShaderUniforms::COLOR, cmd.color); @@ -210,14 +172,24 @@ inline void useExternalShader(AOptional& out, std::string_view vsPa } -ASolidBrush::Data OpenGLRenderer::solidBrush(const IBatchingRenderer::Cmd& cmd, const ASolidBrush& brush, OpenGLRenderer& renderer, gl::Program& shader) { +ASolidBrush::Data OpenGLRenderer::solidBrush(const IBatchingRenderer::Cmd& cmd, const ASolidBrush& brush, gl::Program& shader) { mBatchShader = &shader; - auto color = cmd.color * brush.solidColor; - color.a = 0.5; + auto color = cmd.color * brush.color; return color; } +ALinearGradientBrush::Data OpenGLRenderer::gradientBrush(const IBatchingRenderer::Cmd& cmd, const ALinearGradientBrush& brush, gl::Program& shader) { + mBatchShader = &shader; + auto result = ALinearGradientBrush::Data{ + .colorStart = cmd.color * brush.colorStart, + .colorEnd = cmd.color * brush.colorEnd, + .rotation = brush.rotation.radians() + }; + + return result; +} + OpenGLRenderer::OpenGLRenderer() { ALogger::info(LOG_TAG) << "GL_VERSION = " << ((const char*) glGetString(GL_VERSION)); ALogger::info(LOG_TAG) << "GL_VENDOR = " << ((const char*) glGetString(GL_VENDOR)); @@ -237,11 +209,33 @@ OpenGLRenderer::OpenGLRenderer() { mGradientTexture.setupLinear(); mGradientTexture.setupClampToEdge(); - // useAuislShader(mSolidShader); - useExternalShader(mSolidShader, "aui.views/shaders/basic.vert", "aui.views/shaders/solid.frag"); + useExternalShader(mSolidShader, "aui.views/shaders/basic_solid.vert", "aui.views/shaders/solid.frag"); mSolidShader->bindAttribute(0, "pos"); mSolidShader->bindAttribute(1, "color"); + mSolidShader->setSetupCallback([]() { + glEnableVertexAttribArray(0); + const size_t stride = sizeof(glm::vec4) * 2; + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, stride, 0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, stride, reinterpret_cast(sizeof(glm::vec4))); + }); + + useExternalShader(mGradientShader, "aui.views/shaders/basic_gradient.vert", "aui.views/shaders/gradient.frag"); + mGradientShader->bindAttribute(0, "pos"); + mGradientShader->bindAttribute(1, "color_start"); + mGradientShader->bindAttribute(2, "color_end"); + mGradientShader->bindAttribute(3, "direction"); + mGradientShader->setSetupCallback([]() { + glEnableVertexAttribArray(0); + const size_t stride = sizeof(glm::vec4) * 3 + sizeof(float); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, stride, 0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, stride, reinterpret_cast(sizeof(glm::vec4))); + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, stride, reinterpret_cast(2 * sizeof(glm::vec4))); + glEnableVertexAttribArray(3); + glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, stride, reinterpret_cast(3 * sizeof(glm::vec4))); + }); // useAuislShader(mBoxShadowShader); @@ -254,8 +248,6 @@ OpenGLRenderer::OpenGLRenderer() { // useAuislShader(mRoundedSolidShaderBorder); // useAuislShader(mGradientShader); - // useAuislShader(mRoundedGradientShader); // useAuislShader(mTexturedShader); @@ -272,12 +264,8 @@ OpenGLRenderer::OpenGLRenderer() { // useAuislShader(mLineSolidDashedShader); - { - mRectangleVao.indicesByCount(BATCH_BUFFER_SIZE); - } - { - mRectangleVao.indicesByCount(BATCH_BUFFER_SIZE); - } + mBatchVao.indicesByCount(BATCH_BUFFER_SIZE); + mBatchVao.indicesByCount(BATCH_BUFFER_SIZE); mBatchVertices.fill(0.f); mCurrentBatchVertex = mBatchVertices.begin(); } @@ -299,7 +287,7 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { return result; }; - auto getZIndex = [](Cmd& cmd) -> int16_t { + auto getZIndex = [](Cmd& cmd) -> int16_t { std::optional result; std::visit(aui::lambda_overloaded { @@ -313,7 +301,7 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { return result.value_or(std::numeric_limits::max()); }; for (auto& cmd : cmds) { - cmd.batchId = BatchId { + cmd.batchId = BatchId{ getZIndex(cmd), static_cast(cmd.arg.index()), getBrushId(cmd) @@ -323,7 +311,7 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { return cmdA.batchId.value > cmdB.batchId.value; }); - auto &rectangleVao = mRectangleVao; + auto &batchVao = mBatchVao; auto &batchVertices = mBatchVertices; auto &batchShader = mBatchShader; auto ¤tBatchVertex = mCurrentBatchVertex; @@ -332,14 +320,9 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { return; batchShader->use(); - rectangleVao.insert(0, std::span{batchVertices}, name); + batchVao.insert(0, std::span{batchVertices}, name); // TODO: move this and make it more expandable - glEnableVertexAttribArray(0); - const size_t stride = sizeof(glm::vec4) * 2; - glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, stride, 0); - glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, stride, reinterpret_cast(sizeof(glm::vec4))); - rectangleVao.drawElements(); + batchVao.drawElements(); }; BatchId_t currentBatchId = 0; @@ -414,13 +397,14 @@ std::array OpenGLRenderer::getVerticesForRect(glm::vec2 position, void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const zIndex_t zIndex) { std::visit(aui::lambda_overloaded{ [&](const ALinearGradientBrush& brush) { - // gradientBrush(cmd, brush, *this, *mGradientShader); + ALinearGradientBrush::Data data = gradientBrush(cmd, brush, *mGradientShader); + appendRect(position, size, zIndex, cmd.transform, data); }, [&](const ATexturedBrush& brush) { // texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); }, [&](const ASolidBrush& brush) { - ASolidBrush::Data data = solidBrush(cmd, brush, *this, *mSolidShader); + ASolidBrush::Data data = solidBrush(cmd, brush, *mSolidShader); appendRect(position, size, zIndex, cmd.transform, data); }, [](const ACustomShaderBrush& ) {}, @@ -434,7 +418,7 @@ void OpenGLRenderer::identityUv() { {0, 0}, {1, 0} }; - mRectangleVao.insertIfKeyMismatches(1, std::span{uvs}, "identityUv"); + mBatchVao.insertIfKeyMismatches(1, std::span{uvs}, "identityUv"); } void OpenGLRenderer::renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, @@ -444,9 +428,9 @@ void OpenGLRenderer::renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, const zIndex_t zIndex) { std::visit( aui::lambda_overloaded { - [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mRoundedGradientShader); }, - [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); }, - [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *this, *mRoundedSolidShader); }, + [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mRoundedGradientShader); }, + [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); }, + [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *mRoundedSolidShader); }, [](const ACustomShaderBrush& ) {}, }, brush); identityUv(); @@ -462,9 +446,9 @@ void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, const zIndex_t zIndex) { std::visit( aui::lambda_overloaded { - [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, - [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); }, - [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *this, *mSolidShader); }, + [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mGradientShader); }, + [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); }, + [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *mSolidShader); }, [](const ACustomShaderBrush& ) {}, }, brush); identityUv(); @@ -490,7 +474,7 @@ void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec3(glm::vec4 { x + lineDelta, y, 1, 1 }) }; - mRectangleVao.insert(0, std::span{verticies}, "rectangleBorder"); + mBatchVao.insert(0, std::span{verticies}, "rectangleBorder"); glLineWidth(lineWidth); } @@ -503,9 +487,9 @@ void OpenGLRenderer::renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& const zIndex_t zIndex) { std::visit( aui::lambda_overloaded { - [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, - [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); }, - [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *this, *mRoundedSolidShaderBorder); }, + [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mGradientShader); }, + [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); }, + [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *mRoundedSolidShaderBorder); }, [](const ACustomShaderBrush& ) {}, }, brush); @@ -533,7 +517,7 @@ void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, mBoxShadowShader->set(aui::ShaderUniforms::SL_UNIFORM_UPPER, position); mBoxShadowShader->set(aui::ShaderUniforms::COLOR, cmd.color * color); - mRectangleVao.bind(); + mBatchVao.bind(); float x = position.x; float y = position.y; @@ -575,7 +559,7 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_SIZE, 2.f * borderRadius / size); - mRectangleVao.bind(); + mBatchVao.bind(); float x = position.x; float y = position.y; @@ -964,11 +948,11 @@ bool OpenGLRenderer::setupLineShader(const Cmd& cmd, const ABrush& brush, const [&](const ABorderStyle::Solid&) { std::visit( aui::lambda_overloaded { - [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, + [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mGradientShader); }, [&](const ATexturedBrush& brush) { - texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); + texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); }, - [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *this, *mSolidShader); }, + [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *mSolidShader); }, [](const ACustomShaderBrush&) {}, }, brush); @@ -979,11 +963,11 @@ bool OpenGLRenderer::setupLineShader(const Cmd& cmd, const ABrush& brush, const [&](const ABorderStyle::Dashed& dashed) { std::visit( aui::lambda_overloaded { - [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, + [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mGradientShader); }, [&](const ATexturedBrush& brush) { - texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); + texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); }, - [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *this, *mLineSolidDashedShader); }, + [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *mLineSolidDashedShader); }, [](const ACustomShaderBrush&) {}, }, brush); @@ -1017,7 +1001,7 @@ void OpenGLRenderer::renderLines(const Cmd& cmd, const ABrush& brush, AArrayView gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, cmd.transform); glLineWidth(widthPx); - mRectangleVao.bind(); + mBatchVao.bind(); AVector positions; @@ -1032,8 +1016,8 @@ void OpenGLRenderer::renderLines(const Cmd& cmd, const ABrush& brush, AArrayView positions << LineVertex{point, distanceAccumulator, 1.f}; } - mRectangleVao.insert(0, std::span{positions}, "lines"); - mRectangleVao.drawArrays(GL_LINE_STRIP, points.size()); + mBatchVao.insert(0, std::span{positions}, "lines"); + mBatchVao.drawArrays(GL_LINE_STRIP, points.size()); } void OpenGLRenderer::renderLines(const Cmd& cmd, const ABrush& brush, AArrayView> points, @@ -1043,7 +1027,7 @@ void OpenGLRenderer::renderLines(const Cmd& cmd, const ABrush& brush, AArrayView gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, cmd.transform); glLineWidth(widthPx); - mRectangleVao.bind(); + mBatchVao.bind(); AVector positions; positions.reserve(points.size() * 2); @@ -1061,8 +1045,8 @@ void OpenGLRenderer::renderLines(const Cmd& cmd, const ABrush& brush, AArrayView }; } - mRectangleVao.insert(0, std::span{positions}, "lines"); - mRectangleVao.drawArrays(GL_LINES, positions.size()); + mBatchVao.insert(0, std::span{positions}, "lines"); + mBatchVao.drawArrays(GL_LINES, positions.size()); } void OpenGLRenderer::renderPoints(const Cmd& cmd, const ABrush& brush, AArrayView points, AMetric size) { @@ -1072,9 +1056,9 @@ void OpenGLRenderer::renderPoints(const Cmd& cmd, const ABrush& brush, AArrayVie std::visit( aui::lambda_overloaded { - [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, - [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); }, - [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *this, *mSolidShader); }, + [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mGradientShader); }, + [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); }, + [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *mSolidShader); }, [&](const ACustomShaderBrush& brush) {}, }, brush); @@ -1090,9 +1074,9 @@ void OpenGLRenderer::renderPoints(const Cmd& cmd, const ABrush& brush, AArrayVie #else glPointSize(widthPx); - mRectangleVao.bind(); - mRectangleVao.insert(0, std::span{points}, "lines"); - mRectangleVao.drawArrays(GL_POINTS, points.size()); + mBatchVao.bind(); + mBatchVao.insert(0, std::span{points}, "lines"); + mBatchVao.drawArrays(GL_POINTS, points.size()); #endif } @@ -1103,9 +1087,9 @@ void OpenGLRenderer::renderSquareSector(const Cmd& cmd, const ABrush& brush, AAngleRadians end) { std::visit( aui::lambda_overloaded { - [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *this, *mGradientShader); }, - [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); }, - [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *this, *mSquareSectorShader); }, + [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mGradientShader); }, + [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); }, + [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *mSquareSectorShader); }, [](const ACustomShaderBrush&) {}, }, brush); @@ -1169,7 +1153,7 @@ void OpenGLRenderer::bindTemporaryVao() const noexcept { if (!isVaoAvailable()) { return; } - mRectangleVao.bind(); + mBatchVao.bind(); } _unique OpenGLRenderer::newRenderViewToTexture() noexcept { @@ -1255,7 +1239,7 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept auto vertices = ranges::views::transform(*rectangles, [&](const ARect& r) { return getVerticesForRect(r.p1, r.size()); }) | ranges::views::join | ranges::to(); - mRenderer.mRectangleVao.insert(0, std::span(vertices), "render-to-texture invalid areas"); + mRenderer.mBatchVao.insert(0, std::span(vertices), "render-to-texture invalid areas"); auto indices = ranges::views::generate([i = 0]() mutable { int offset = 4 * i++; return std::array{GLuint(offset + 0), @@ -1269,16 +1253,16 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept | ranges::to() ; static constexpr auto DEFAULT_INDICES_SIZE = 6; - if (indices.size() != DEFAULT_INDICES_SIZE) mRenderer.mRectangleVao.indices(std::span{indices}); + if (indices.size() != DEFAULT_INDICES_SIZE) mRenderer.mBatchVao.indices(std::span{indices}); AUI_DEFER { if (indices.size() != DEFAULT_INDICES_SIZE) { - mRenderer.mRectangleVao.indices(std::span{indices.data(),6 }); + mRenderer.mBatchVao.indices(std::span{indices.data(),6 }); } }; mRenderer.mSolidShader->use(); // mRenderer.uploadToShaderCommon(); // TODO mRenderer.mSolidShader->set(aui::ShaderUniforms::COLOR, glm::vec4(0.f)); - mRenderer.mRectangleVao.drawElements(); + mRenderer.mBatchVao.drawElements(); } return true; @@ -1323,7 +1307,7 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept {0, 1}, {1, 1} }; - mRenderer.mRectangleVao.insertIfKeyMismatches(1, std::span{uvs}, "OpenGLRenderViewToTexture"); + mRenderer.mBatchVao.insertIfKeyMismatches(1, std::span{uvs}, "OpenGLRenderViewToTexture"); // mRenderer.drawRectImpl({0, 0}, mFramebuffer.size()); if (auto& p = AWindow::current()->profiling(); p && p->renderToTextureDecay) [[unlikely]] { // decays to fast. attach it to time @@ -1469,8 +1453,8 @@ void OpenGLRenderer::backdrops(glm::ivec2 position, glm::ivec2 size, std::span(); - shader->loadVertexShader( - std::string(aui::sl_gen::basic_uv::vsh::glsl120::Shader::code())); + // shader->loadVertexShader( + // std::string(aui::sl_gen::basic_uv::vsh::glsl120::Shader::code())); shader->loadFragmentShader( R"( precision highp float; @@ -1491,7 +1475,7 @@ void main() { } )"); - aui::sl_gen::basic_uv::vsh::glsl120::Shader::setup(shader->handle()); + // aui::sl_gen::basic_uv::vsh::glsl120::Shader::setup(shader->handle()); shader->compile(); shader->use(); shader->set(gl::Program::Uniform("uvmap"), 1); @@ -1566,8 +1550,8 @@ void main() { auto kernel = aui::detail::gaussianKernel(radius); - result.shader->loadVertexShader( - std::string(aui::sl_gen::basic_uv::vsh::glsl120::Shader::code())); + // result.shader->loadVertexShader( + // std::string(aui::sl_gen::basic_uv::vsh::glsl120::Shader::code())); result.shader->loadFragmentShader( fmt::format( R"( @@ -1594,7 +1578,7 @@ void main() {{ fmt::arg("radius", radius), fmt::arg("kernel_size", kernel.size()))); - aui::sl_gen::basic_uv::vsh::glsl120::Shader::setup(result.shader->handle()); + // aui::sl_gen::basic_uv::vsh::glsl120::Shader::setup(result.shader->handle()); result.shader->compile(); result.shader->use(); result.shader->setArray(aui::ShaderUniforms::KERNEL, kernel); @@ -1670,7 +1654,7 @@ void main() {{ { 0, uv.y }, { uv.x, uv.y }, }; - mRectangleVao.insertIfKeyMismatches(1, std::span{uvs}, "backdrops"); + mBatchVao.insertIfKeyMismatches(1, std::span{uvs}, "backdrops"); } auto& texture = areaOfInterest->framebuffer->rendertarget->texture(); diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.h b/aui.views/src/AUI/GL/OpenGLRenderer.h index 2ab85bfc0..ef1280a72 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.h +++ b/aui.views/src/AUI/GL/OpenGLRenderer.h @@ -71,11 +71,10 @@ friend class OpenGLMultiStringCanvas; AOptional mSymbolShaderSubPixel; AOptional mSquareSectorShader; AOptional mLineSolidDashedShader; - static constexpr size_t BATCH_BUFFER_SIZE = 20000; + static constexpr size_t BATCH_BUFFER_SIZE = 40000; std::array mBatchVertices; std::array::iterator mCurrentBatchVertex; - gl::Vao mRectangleVao; - gl::Vao mBorderVao; + gl::Vao mBatchVao; gl::Texture2D mGradientTexture; gl::Program* mBatchShader; @@ -137,8 +136,9 @@ friend class OpenGLMultiStringCanvas; FramebufferFromPool getFramebufferForMultiPassEffect(glm::uvec2 minRequiredSize); static constexpr size_t Z_DEPTH = 1000; - template - void appendRect(const glm::vec2 position, const glm::vec2 size, const zIndex_t zIndex, const glm::mat4 transform, glm::vecadditionalData) { + template + void appendRect(const glm::vec2 position, const glm::vec2 size, const zIndex_t zIndex, const glm::mat4 transform, T additionalData) { + static_assert(std::is_trivially_copyable_v); float x = position.x; float y = position.y; float w = x + size.x; @@ -159,13 +159,14 @@ friend class OpenGLMultiStringCanvas; } } - template - void appendVertexData(glm::vec data) { - std::memcpy(mCurrentBatchVertex, glm::value_ptr(data), sizeof(float) * L); - mCurrentBatchVertex += L; + template + void appendVertexData(T data) { + std::memcpy(mCurrentBatchVertex, &data, sizeof(T)); + mCurrentBatchVertex += sizeof(T) / sizeof(float); } - ASolidBrush::Data solidBrush(const IBatchingRenderer::Cmd& cmd, const ASolidBrush& brush, OpenGLRenderer& renderer, gl::Program& shader); + ASolidBrush::Data solidBrush(const IBatchingRenderer::Cmd& cmd, const ASolidBrush& brush, gl::Program& shader); + ALinearGradientBrush::Data gradientBrush(const IBatchingRenderer::Cmd& cmd, const ALinearGradientBrush& brush, gl::Program& shader); private: // Helper methods that perform the actual rendering for each command. diff --git a/aui.views/src/AUI/GL/Program.cpp b/aui.views/src/AUI/GL/Program.cpp index dff72f03d..0c91f9572 100644 --- a/aui.views/src/AUI/GL/Program.cpp +++ b/aui.views/src/AUI/GL/Program.cpp @@ -112,6 +112,8 @@ void gl::Program::compile() { void gl::Program::use() const { gl::State::useProgram(mProgram); currentShader() = const_cast(this); + if (mSetupCallback) + mSetupCallback(); } void gl::Program::bindAttribute(uint32_t index, const AString& name) { @@ -120,6 +122,10 @@ void gl::Program::bindAttribute(uint32_t index, const AString& name) { glBindAttribLocation(mProgram, index, name.toStdString().c_str()); } +void gl::Program::setSetupCallback(SetupCallback value) { + mSetupCallback = value; +} + void gl::Program::set(const gl::Program::Uniform& uniform, glm::mat4 value) const { if (sameAsCache(uniform, value)) return; diff --git a/aui.views/src/AUI/GL/Program.h b/aui.views/src/AUI/GL/Program.h index f90ffd77d..3c2afd3a8 100644 --- a/aui.views/src/AUI/GL/Program.h +++ b/aui.views/src/AUI/GL/Program.h @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -43,6 +44,8 @@ struct GLSLOptions { class API_AUI_VIEWS Program: public aui::noncopyable { public: + using SetupCallback = void(); + class API_AUI_VIEWS Uniform { private: const char* mUniformString; @@ -73,6 +76,7 @@ class API_AUI_VIEWS Program: public aui::noncopyable { } void compile(); void bindAttribute(uint32_t index, const AString& name); + void setSetupCallback(SetupCallback value); void use() const; ~Program(); Program(const Program&) = delete; @@ -113,6 +117,7 @@ class API_AUI_VIEWS Program: public aui::noncopyable { uint32_t mVertex = 0; uint32_t mFragment = 0; + std::function mSetupCallback; class UniformState { public: enum Value { UNINITIALIZED = -2, DOES_NOT_EXIST = -1 }; diff --git a/aui.views/src/AUI/Render/ABrush.h b/aui.views/src/AUI/Render/ABrush.h index 129774830..c6e3fc7bd 100644 --- a/aui.views/src/AUI/Render/ABrush.h +++ b/aui.views/src/AUI/Render/ABrush.h @@ -31,7 +31,8 @@ * The simplest brush which used single solid color to fill. */ struct ASolidBrush { - AColor solidColor = AColor::WHITE; + AColor color = AColor::WHITE; + using Data = glm::vec4; }; @@ -48,12 +49,8 @@ struct ACustomShaderBrush { * Brush which produces linear gradient by rectangle. */ struct ALinearGradientBrush { - struct ColorEntry { - aui::float_within_0_1 position; - AColor color; - }; - AVector colors; - + AColor colorStart; + AColor colorEnd; /** * @brief Clockwise gradient angle. * @details @@ -62,6 +59,12 @@ struct ALinearGradientBrush { * direction. */ AAngleRadians rotation = 180_deg; + + using Data = struct { + AColor colorStart; + AColor colorEnd; + float rotation; + }; }; class ITexture; diff --git a/aui.views/src/AUI/Render/Brush/Gradient.h b/aui.views/src/AUI/Render/Brush/Gradient.h index 7f874482a..0581dfc24 100644 --- a/aui.views/src/AUI/Render/Brush/Gradient.h +++ b/aui.views/src/AUI/Render/Brush/Gradient.h @@ -21,9 +21,8 @@ namespace aui::render::brush::gradient { glm::mat3 matrix; Helper(const ALinearGradientBrush& brush) { - for (const auto& c : brush.colors) { - colors.push_back(glm::uvec4(c.color * 255.f)); - } + colors.push_back(glm::uvec4(brush.colorStart * 255.f)); + colors.push_back(glm::uvec4(brush.colorEnd * 255.f)); //float actualEdgeUvPosition = (0.5f - 0.05f /* bias to make ideal color edge */) / float(colors.size()); float actualEdgeUvPosition = 0.f; // temporary @@ -66,4 +65,4 @@ namespace aui::render::brush::gradient { return AImageView({(const char*)colors.data(), colors.sizeInBytes()}, {colors.size(), 1}, APixelFormat::RGBA_BYTE); } }; -} \ No newline at end of file +} diff --git a/aui.views/src/AUI/Software/SoftwareRenderer.cpp b/aui.views/src/AUI/Software/SoftwareRenderer.cpp index a43d43d56..93bf116b7 100644 --- a/aui.views/src/AUI/Software/SoftwareRenderer.cpp +++ b/aui.views/src/AUI/Software/SoftwareRenderer.cpp @@ -21,9 +21,9 @@ #include "SoftwareTexture.h" #include "AUI/Render/Brush/Gradient.h" #include "glm/vector_relational.hpp" -#include -#include -#include +// #include +// #include +// #include struct BrushHelper { SoftwareRenderer* renderer; @@ -38,11 +38,11 @@ struct BrushHelper { glm::ivec2& position) : renderer(renderer), x(x), y(y), end(end), position(position) {} void operator()(const ASolidBrush& brush) noexcept { - using namespace aui::sl_gen::rect_solid::fsh::software; - - renderer->putPixel({x, y}, Shader::entry({}, Shader::Uniform { - .color = renderer->getColor() * brush.solidColor - }).albedo); + // using namespace aui::sl_gen::rect_solid::fsh::software; + // + // renderer->putPixel({x, y}, Shader::entry({}, Shader::Uniform { + // .color = renderer->getColor() * brush.solidColor + // }).albedo); } void operator()(const ATexturedBrush& brush) noexcept { @@ -77,18 +77,18 @@ struct BrushHelper { void operator()(const ALinearGradientBrush& brush) noexcept { - using namespace aui::sl_gen::rect_gradient::fsh::software; - - aui::render::brush::gradient::Helper h(brush); - const auto output = Shader::entry({.uv = calculateUv()}, - { - //.gradientMap = aui::sl_gen::Texture2D(h.gradientMap(), ImageRendering::SMOOTH), - .color1 = h.colors[0], - .color2 = h.colors[1], - .matUv = h.matrix, - .color = renderer->getColor() - }); - renderer->putPixel({ x, y }, output.albedo); + // using namespace aui::sl_gen::rect_gradient::fsh::software; + // + // aui::render::brush::gradient::Helper h(brush); + // const auto output = Shader::entry({.uv = calculateUv()}, + // { + // //.gradientMap = aui::sl_gen::Texture2D(h.gradientMap(), ImageRendering::SMOOTH), + // .color1 = h.colors[0], + // .color2 = h.colors[1], + // .matUv = h.matrix, + // .color = renderer->getColor() + // }); + // renderer->putPixel({ x, y }, output.albedo); } void operator()(const ACustomShaderBrush& brush) noexcept { @@ -284,28 +284,28 @@ void SoftwareRenderer::boxShadow(glm::vec2 position, auto iSize = glm::ivec2(size + blurRadius * 2.f); - using namespace aui::sl_gen::shadow::fsh::software; - const Shader::Uniform uniform{ - .color = mColor * color, - .lower = transformedPos + size, - .upper = transformedPos, - .sigma = blurRadius / 2.f, - }; - - for (int y = 0; y < iSize.y; ++y) { - for (int x = 0; x < iSize.x; ++x) { - const auto result = Shader::entry(Shader::Inter { - .vertex = glm::ivec4(iTransformedPos + glm::ivec2{x, y}, 0, 1), - }, uniform).albedo; - - /* - glm::vec4 query = glm::vec4(pass_uv - glm::vec2(lower), pass_uv - glm::vec2(upper)); - glm::vec4 integral = 0.5f + 0.5f * erf(query * (glm::sqrt(0.5f) / sigma)); - float alpha = glm::clamp((integral.z - integral.x) * (integral.w - integral.y), 0.0f, 1.0f); -*/ - putPixel(iTransformedPos + glm::ivec2{ x, y }, result); - } - } +// using namespace aui::sl_gen::shadow::fsh::software; +// const Shader::Uniform uniform{ +// .color = mColor * color, +// .lower = transformedPos + size, +// .upper = transformedPos, +// .sigma = blurRadius / 2.f, +// }; +// +// for (int y = 0; y < iSize.y; ++y) { +// for (int x = 0; x < iSize.x; ++x) { +// const auto result = Shader::entry(Shader::Inter { +// .vertex = glm::ivec4(iTransformedPos + glm::ivec2{x, y}, 0, 1), +// }, uniform).albedo; +// +// /* +// glm::vec4 query = glm::vec4(pass_uv - glm::vec2(lower), pass_uv - glm::vec2(upper)); +// glm::vec4 integral = 0.5f + 0.5f * erf(query * (glm::sqrt(0.5f) / sigma)); +// float alpha = glm::clamp((integral.z - integral.x) * (integral.w - integral.y), 0.0f, 1.0f); +// */ +// putPixel(iTransformedPos + glm::ivec2{ x, y }, result); +// } +// } } void SoftwareRenderer::boxShadowInner(glm::vec2 position, zIndex_t zIndex, @@ -323,28 +323,28 @@ void SoftwareRenderer::boxShadowInner(glm::vec2 position, auto iSize = glm::ivec2(size + blurRadius * 2.f); - using namespace aui::sl_gen::shadow::fsh::software; - const Shader::Uniform uniform{ - .color = mColor * color, - .lower = size, - .upper = transformedPos, - .sigma = blurRadius / 2.f, - }; + // using namespace aui::sl_gen::shadow::fsh::software; + // const Shader::Uniform uniform{ + // .color = mColor * color, + // .lower = size, + // .upper = transformedPos, + // .sigma = blurRadius / 2.f, + // }; - for (int y = 0; y < iSize.y; ++y) { - for (int x = 0; x < iSize.x; ++x) { - const auto result = Shader::entry(Shader::Inter { - .vertex = glm::vec4(transformedPos + glm::vec2{x, y}, 0.f, 1.f), - }, uniform).albedo; - - /* - glm::vec4 query = glm::vec4(pass_uv - glm::vec2(lower), pass_uv - glm::vec2(upper)); - glm::vec4 integral = 0.5f + 0.5f * erf(query * (glm::sqrt(0.5f) / sigma)); - float alpha = glm::clamp((integral.z - integral.x) * (integral.w - integral.y), 0.0f, 1.0f); -*/ - putPixel(iTransformedPos + glm::ivec2{ x, y }, result); - } - } +// for (int y = 0; y < iSize.y; ++y) { +// for (int x = 0; x < iSize.x; ++x) { +// const auto result = Shader::entry(Shader::Inter { +// .vertex = glm::vec4(transformedPos + glm::vec2{x, y}, 0.f, 1.f), +// }, uniform).albedo; +// +// /* +// glm::vec4 query = glm::vec4(pass_uv - glm::vec2(lower), pass_uv - glm::vec2(upper)); +// glm::vec4 integral = 0.5f + 0.5f * erf(query * (glm::sqrt(0.5f) / sigma)); +// float alpha = glm::clamp((integral.z - integral.x) * (integral.w - integral.y), 0.0f, 1.0f); +// */ +// putPixel(iTransformedPos + glm::ivec2{ x, y }, result); +// } +// } } diff --git a/aui.views/src/AUI/View/AView.cpp b/aui.views/src/AUI/View/AView.cpp index 8d1f4b5f9..b73e0e60e 100644 --- a/aui.views/src/AUI/View/AView.cpp +++ b/aui.views/src/AUI/View/AView.cpp @@ -103,11 +103,11 @@ void AView::drawStencilMask(ARenderContext ctx) switch (mOverflowMask) { case AOverflowMask::ROUNDED_RECT: if (mBorderRadius > 0) { - ctx.render.roundedRectangle(ASolidBrush{}, - {mPadding.left, mPadding.top}, - mZIndex, - {getWidth() - mPadding.horizontal(), getHeight() - mPadding.vertical()}, - glm::max(mBorderRadius - std::min(mPadding.horizontal(), mPadding.vertical()), 0.f)); + // ctx.render.roundedRectangle(ASolidBrush{}, + // {mPadding.left, mPadding.top}, + // mZIndex, + // {getWidth() - mPadding.horizontal(), getHeight() - mPadding.vertical()}, + // glm::max(mBorderRadius - std::min(mPadding.horizontal(), mPadding.vertical()), 0.f)); } else { // TODO: figure out why this is rendered opaque when batching // ctx.render.rectangle(ASolidBrush{}, diff --git a/examples/ui/game_inventory/src/main.cpp b/examples/ui/game_inventory/src/main.cpp index 86bb017c1..2a0021622 100644 --- a/examples/ui/game_inventory/src/main.cpp +++ b/examples/ui/game_inventory/src/main.cpp @@ -13,6 +13,7 @@ #include "AUI/ASS/Property/Margin.h" #include "AUI/Common/AColor.h" #include "AUI/Platform/ARenderingContextOptions.h" +#include "AUI/Util/AAngleRadians.h" #include "AUI/View/AForEachUI.h" #include "AUI/View/AScrollArea.h" #include "AUI/View/Dynamic.h" @@ -56,7 +57,7 @@ _ itemStackView(const _>>& itemStack) { AObject::connect( AUI_REACT(ass::PropertyListRecursive { // BackgroundImage { (*itemStack) ->hasValue() ? ":texture/item/{}.png"_format((**itemStack)->id) : "" }, - BackgroundSolid{ AColor{ "#FB1816" }}, + BackgroundGradient{ AColor{ "#FB181655" }, AColor{ "#1BF81655" }, 90_deg }, Expanding {}, }), AUI_SLOT(it)::setCustomStyle); From ea9223912a28be4c6ea431dbda7addaaf9f52faf Mon Sep 17 00:00:00 2001 From: ivn-ln Date: Mon, 23 Mar 2026 21:46:27 +0300 Subject: [PATCH 22/22] batching: ordering fix --- .gitignore | 3 + aui.views/src/AUI/GL/IBatchingRenderer.h | 2 +- aui.views/src/AUI/GL/OpenGLRenderer.cpp | 800 +++++++++--------- aui.views/src/AUI/GL/OpenGLRenderer.h | 4 +- aui.views/src/AUI/View/AView.cpp | 7 +- aui.views/src/AUI/View/AView.h | 2 +- aui.views/src/AUI/View/AViewContainerBase.cpp | 8 + aui.views/src/AUI/View/AViewContainerBase.h | 2 + 8 files changed, 399 insertions(+), 429 deletions(-) diff --git a/.gitignore b/.gitignore index 757ee156c..3d5e92294 100644 --- a/.gitignore +++ b/.gitignore @@ -360,3 +360,6 @@ site/ # clangd compile commands compile_commands.json + +# gdb config +.gdbinit diff --git a/aui.views/src/AUI/GL/IBatchingRenderer.h b/aui.views/src/AUI/GL/IBatchingRenderer.h index a9906c627..c8b73600a 100644 --- a/aui.views/src/AUI/GL/IBatchingRenderer.h +++ b/aui.views/src/AUI/GL/IBatchingRenderer.h @@ -97,7 +97,7 @@ class IBatchingRenderer : public IRenderer { BatchId_t value; BatchId() : value{std::numeric_limits::max()} {}; BatchId(int16_t z, uint8_t cmd, uint8_t brush) { - value = static_cast(z) << 16 | static_cast(cmd << 8) | static_cast(brush); + value = (static_cast(z) << 16) | (static_cast(cmd) << 8) | static_cast(brush); } auto operator<=>(const BatchId&) const = default; }; diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.cpp b/aui.views/src/AUI/GL/OpenGLRenderer.cpp index 64e9acf19..e13111b3b 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.cpp +++ b/aui.views/src/AUI/GL/OpenGLRenderer.cpp @@ -68,17 +68,11 @@ class OpenGLTexture2D : public ITexture { gl::Texture2D mTexture; public: - void setImage(AImageView image) override { - mTexture.tex2D(image); - } + void setImage(AImageView image) override { mTexture.tex2D(image); } - void bind() { - mTexture.bind(); - } + void bind() { mTexture.bind(); } - gl::Texture2D& texture() noexcept { - return mTexture; - } + gl::Texture2D& texture() noexcept { return mTexture; } }; /** @@ -86,23 +80,24 @@ class OpenGLTexture2D : public ITexture { */ static constexpr auto UV_BIAS = 0.001f; - namespace { -void texturedBrush(const IBatchingRenderer::Cmd& cmd, const ATexturedBrush& brush, OpenGLRenderer& renderer, gl::Program& shader, gl::Vao& tempVao) { +void texturedBrush( + const IBatchingRenderer::Cmd& cmd, const ATexturedBrush& brush, OpenGLRenderer& renderer, gl::Program& shader, + gl::Vao& tempVao) { shader.use(); shader.set(aui::ShaderUniforms::COLOR, cmd.color); if (brush.uv1 || brush.uv2) { - glm::vec2 uv1 = brush.uv1.valueOr(glm::vec2{0, 0}); - glm::vec2 uv2 = brush.uv2.valueOr(glm::vec2{1, 1}); + glm::vec2 uv1 = brush.uv1.valueOr(glm::vec2 { 0, 0 }); + glm::vec2 uv2 = brush.uv2.valueOr(glm::vec2 { 1, 1 }); const glm::vec2 uvs[] = { - {uv1.x, uv2.y}, - {uv2.x, uv2.y}, - {uv1.x, uv1.y}, - {uv2.x, uv1.y}, + { uv1.x, uv2.y }, + { uv2.x, uv2.y }, + { uv1.x, uv1.y }, + { uv2.x, uv1.y }, }; - tempVao.insert(1, std::span{uvs}, "TexturedShaderHelper"); + tempVao.insert(1, std::span { uvs }, "TexturedShaderHelper"); } else { renderer.identityUv(); } @@ -132,14 +127,13 @@ void texturedBrush(const IBatchingRenderer::Cmd& cmd, const ATexturedBrush& brus } } - -template +template concept AuiSLShader = requires(C&& c) { { C::code() } -> std::same_as; C::setup(0); }; -template +template inline void useAuislShader(AOptional& out) { out.emplace(); out->loadBoth(Vertex::code(), Fragment::code()); @@ -152,12 +146,12 @@ inline void useAuislShader(AOptional& out) { inline void useExternalShader(AOptional& out, std::string_view vsPath, std::string_view fsPath) { out.emplace(); ALogger::info("OpenGL") << std::format("Loading vertex shader {}", vsPath); - std::ifstream vsFile{ static_cast(vsPath) }; + std::ifstream vsFile { static_cast(vsPath) }; if (!vsFile.is_open()) { throw AException("Couldn't open vertex shader " + vsPath); } ALogger::info("OpenGL") << std::format("Loading fragment shader {}", fsPath); - std::ifstream fsFile{ static_cast(fsPath) }; + std::ifstream fsFile { static_cast(fsPath) }; if (!fsFile.is_open()) { throw AException("Couldn't open fragment shader" + fsPath); } @@ -165,26 +159,28 @@ inline void useExternalShader(AOptional& out, std::string_view vsPa vsBuffer << vsFile.rdbuf(); std::stringstream fsBuffer; fsBuffer << fsFile.rdbuf(); - out->loadVertexShader(vsBuffer.str(), gl::GLSLOptions{.custom=true}); - out->loadFragmentShader(fsBuffer.str(), gl::GLSLOptions{.custom=true}); + out->loadVertexShader(vsBuffer.str(), gl::GLSLOptions { .custom = true }); + out->loadFragmentShader(fsBuffer.str(), gl::GLSLOptions { .custom = true }); out->compile(); } -} +} // namespace -ASolidBrush::Data OpenGLRenderer::solidBrush(const IBatchingRenderer::Cmd& cmd, const ASolidBrush& brush, gl::Program& shader) { +ASolidBrush::Data +OpenGLRenderer::solidBrush(const IBatchingRenderer::Cmd& cmd, const ASolidBrush& brush, gl::Program& shader) { mBatchShader = &shader; auto color = cmd.color * brush.color; return color; } -ALinearGradientBrush::Data OpenGLRenderer::gradientBrush(const IBatchingRenderer::Cmd& cmd, const ALinearGradientBrush& brush, gl::Program& shader) { +ALinearGradientBrush::Data OpenGLRenderer::gradientBrush( + const IBatchingRenderer::Cmd& cmd, const ALinearGradientBrush& brush, gl::Program& shader) { mBatchShader = &shader; - auto result = ALinearGradientBrush::Data{ + auto result = ALinearGradientBrush::Data { .colorStart = cmd.color * brush.colorStart, .colorEnd = cmd.color * brush.colorEnd, - .rotation = brush.rotation.radians() + .rotation = brush.rotation.radians() }; return result; @@ -195,11 +191,11 @@ OpenGLRenderer::OpenGLRenderer() { ALogger::info(LOG_TAG) << "GL_VENDOR = " << ((const char*) glGetString(GL_VENDOR)); ALogger::info(LOG_TAG) << "GL_RENDERER = " << ((const char*) glGetString(GL_RENDERER)); ALogger::info(LOG_TAG) << "GL_EXTENSIONS = " << [] { - if (auto ext = ((const char*) glGetString(GL_EXTENSIONS))) { - return ext; - } else { - return "null"; - } + if (auto ext = ((const char*) glGetString(GL_EXTENSIONS))) { + return ext; + } else { + return "null"; + } }(); #if AUI_DEBUG && (AUI_PLATFORM_WIN || AUI_PLATFORM_LINUX) gl::setupDebug(); @@ -275,52 +271,48 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { unsigned char result; const char OFFSET = 3; - std::visit(aui::lambda_overloaded { - [&](const auto& arg) { + std::visit( + aui::lambda_overloaded { [&](const auto& arg) { if constexpr (requires { arg.brush; }) { result = arg.brush.index() + OFFSET; } else { result = OFFSET - 1; } - } - }, cmd.arg); + } }, + cmd.arg); return result; }; - auto getZIndex = [](Cmd& cmd) -> int16_t { + auto getZIndex = [](const Cmd& cmd) -> int16_t { std::optional result; - std::visit(aui::lambda_overloaded { - [&](const auto& arg) { + std::visit( + aui::lambda_overloaded { [&](const auto& arg) { if constexpr (requires { arg.zIndex; }) { result = arg.zIndex; } - } - }, cmd.arg); + } }, + cmd.arg); return result.value_or(std::numeric_limits::max()); }; for (auto& cmd : cmds) { - cmd.batchId = BatchId{ - getZIndex(cmd), - static_cast(cmd.arg.index()), - getBrushId(cmd) - }; + cmd.batchId = BatchId { getZIndex(cmd), static_cast(cmd.arg.index()), getBrushId(cmd) }; } - std::ranges::stable_sort(cmds, [](const Cmd& cmdA, const Cmd& cmdB) { - return cmdA.batchId.value > cmdB.batchId.value; + std::ranges::stable_sort(cmds, [&](const Cmd& cmdA, const Cmd& cmdB) { + return cmdA.batchId.value < cmdB.batchId.value; }); - auto &batchVao = mBatchVao; - auto &batchVertices = mBatchVertices; - auto &batchShader = mBatchShader; - auto ¤tBatchVertex = mCurrentBatchVertex; - auto drawBatch = [&](const char *name) { + auto& batchVao = mBatchVao; + auto& batchVertices = mBatchVertices; + auto& batchShader = mBatchShader; + auto& currentBatchVertex = mCurrentBatchVertex; + auto drawBatch = [&](const char* name) { if (batchShader == nullptr or currentBatchVertex == batchVertices.begin()) return; batchShader->use(); - batchVao.insert(0, std::span{batchVertices}, name); + batchVao.insert(0, std::span { batchVertices }, name); // TODO: move this and make it more expandable batchVao.drawElements(); }; @@ -328,7 +320,7 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { BatchId_t currentBatchId = 0; bool breakBatch = false; auto dispatch = [&](Cmd& cmd) { - BatchId_t nextId = cmd.batchId.value + 1; // + 1 so 0 ID cmd 0 ID brush != NULL + BatchId_t nextId = cmd.batchId.value + 1; // + 1 so 0 ID cmd 0 ID brush != NULL if (!currentBatchId) { currentBatchId = nextId; return; @@ -351,32 +343,37 @@ void OpenGLRenderer::handleCmds(std::vector cmds) { for (auto& cmd : cmds) { dispatch(cmd); - std::visit(aui::lambda_overloaded{ - [&](const CmdRectangle& c) { renderRectangle(cmd, c.brush, c.position, c.size, c.zIndex); }, - // [&](const CmdRoundedRectangle& c) { renderRoundedRectangle(cmd, c.brush, c.position, c.size, c.radius, c.zIndex); }, - // [&](const CmdRectangleBorder& c) { renderRectangleBorder(cmd, c.brush, c.position, c.size, c.lineWidth, c.zIndex); }, - // [&](const CmdRoundedRectangleBorder& c) { renderRoundedRectangleBorder(cmd, c.brush, c.position, c.size, c.radius, c.borderWidth, c.zIndex); }, - // [&](const CmdBoxShadow& c) { renderBoxShadow(cmd, c.position, c.size, c.blurRadius, c.color, c.zIndex); }, - // [&](const CmdBoxShadowInner& c) { renderBoxShadowInner(cmd, c.position, c.size, c.blurRadius, c.spreadRadius, c.borderRadius, c.color, c.offset, c.zIndex); }, - // [&](const CmdString& c) { renderString(cmd, c.position, c.string, c.fs); }, - // [&](const CmdLines& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, - // [&](const CmdPoints& c) { renderPoints(cmd, c.brush, c.points, c.size); }, - // [&](const CmdLinesPairs& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, - // [&](const CmdSquareSector& c) { renderSquareSector(cmd, c.brush, c.position, c.size, c.begin, c.end); }, - // [&](const CmdSetWindow& c) { mWindow = c.window; }, - // [&](const CmdNewRenderViewToTexture&){ /* handled elsewhere */ }, - [&](const auto &c){ } - }, cmd.arg); + std::visit( + aui::lambda_overloaded { + [&](const CmdRectangle& c) { renderRectangle(cmd, c.brush, c.position, c.size, c.zIndex); }, + // [&](const CmdRoundedRectangle& c) { renderRoundedRectangle(cmd, c.brush, c.position, c.size, c.radius, + // c.zIndex); }, + // [&](const CmdRectangleBorder& c) { renderRectangleBorder(cmd, c.brush, c.position, c.size, c.lineWidth, + // c.zIndex); }, + // [&](const CmdRoundedRectangleBorder& c) { renderRoundedRectangleBorder(cmd, c.brush, c.position, + // c.size, c.radius, c.borderWidth, c.zIndex); }, + // [&](const CmdBoxShadow& c) { renderBoxShadow(cmd, c.position, c.size, c.blurRadius, c.color, c.zIndex); + // }, + // [&](const CmdBoxShadowInner& c) { renderBoxShadowInner(cmd, c.position, c.size, c.blurRadius, + // c.spreadRadius, c.borderRadius, c.color, c.offset, c.zIndex); }, + // [&](const CmdString& c) { renderString(cmd, c.position, c.string, c.fs); }, + // [&](const CmdLines& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, + // [&](const CmdPoints& c) { renderPoints(cmd, c.brush, c.points, c.size); }, + // [&](const CmdLinesPairs& c) { renderLines(cmd, c.brush, c.points, c.style, c.width); }, + // [&](const CmdSquareSector& c) { renderSquareSector(cmd, c.brush, c.position, c.size, c.begin, c.end); + // }, + // [&](const CmdSetWindow& c) { mWindow = c.window; }, + // [&](const CmdNewRenderViewToTexture&){ /* handled elsewhere */ }, + [&](const auto& c) {} }, + cmd.arg); } if (mCurrentBatchVertex != mBatchVertices.begin()) drawBatch("Batch"); } - glm::mat4 OpenGLRenderer::getProjectionMatrix() const { - return glm::ortho(0.0f, static_cast(mWindow->getWidth()), - static_cast(mWindow->getHeight()), 0.0f, - -1.f, 1.f); + return glm::ortho( + 0.0f, static_cast(mWindow->getWidth()), static_cast(mWindow->getHeight()), 0.0f, -1.f, 1.f); } std::array OpenGLRenderer::getVerticesForRect(glm::vec2 position, glm::vec2 size) { @@ -385,75 +382,81 @@ std::array OpenGLRenderer::getVerticesForRect(glm::vec2 position, float w = x + size.x; float h = y + size.y; - return - { - glm::vec2{x, h,}, - glm::vec2{w, h,}, - glm::vec2{x, y,}, - glm::vec2{w, y,}, - }; -} - -void OpenGLRenderer::renderRectangle(const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const zIndex_t zIndex) { - std::visit(aui::lambda_overloaded{ - [&](const ALinearGradientBrush& brush) { - ALinearGradientBrush::Data data = gradientBrush(cmd, brush, *mGradientShader); - appendRect(position, size, zIndex, cmd.transform, data); + return { + glm::vec2 { + x, + h, + }, + glm::vec2 { + w, + h, }, - [&](const ATexturedBrush& brush) { - // texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); + glm::vec2 { + x, + y, }, - [&](const ASolidBrush& brush) { - ASolidBrush::Data data = solidBrush(cmd, brush, *mSolidShader); - appendRect(position, size, zIndex, cmd.transform, data); + glm::vec2 { + w, + y, }, - [](const ACustomShaderBrush& ) {}, - }, brush); + }; +} + +void OpenGLRenderer::renderRectangle( + const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, const zIndex_t zIndex) { + std::visit( + aui::lambda_overloaded { + [&](const ALinearGradientBrush& brush) { + ALinearGradientBrush::Data data = gradientBrush(cmd, brush, *mGradientShader); + appendRect(position, size, cmd.transform, data); + }, + [&](const ATexturedBrush& brush) { + // texturedBrush(cmd, brush, *this, *mTexturedShader, mRectangleVao); + }, + [&](const ASolidBrush& brush) { + ASolidBrush::Data data = solidBrush(cmd, brush, *mSolidShader); + appendRect(position, size, cmd.transform, data); + }, + [](const ACustomShaderBrush&) {}, + }, + brush); } void OpenGLRenderer::identityUv() { - const glm::vec2 uvs[] = { - {0, 1}, - {1, 1}, - {0, 0}, - {1, 0} - }; - mBatchVao.insertIfKeyMismatches(1, std::span{uvs}, "identityUv"); + const glm::vec2 uvs[] = { { 0, 1 }, { 1, 1 }, { 0, 0 }, { 1, 0 } }; + mBatchVao.insertIfKeyMismatches(1, std::span { uvs }, "identityUv"); } -void OpenGLRenderer::renderRoundedRectangle(const Cmd& cmd, const ABrush& brush, - glm::vec2 position, - glm::vec2 size, - float radius, - const zIndex_t zIndex) { +void OpenGLRenderer::renderRoundedRectangle( + const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, const zIndex_t zIndex) { std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mRoundedGradientShader); }, [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); }, [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *mRoundedSolidShader); }, - [](const ACustomShaderBrush& ) {}, - }, brush); + [](const ACustomShaderBrush&) {}, + }, + brush); identityUv(); gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_SIZE, 2.f * radius / size); // appendRect(position, size, zIndex, cmd.transform); } -void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, - glm::vec2 position, - glm::vec2 size, - float lineWidth, - const zIndex_t zIndex) { +void OpenGLRenderer::renderRectangleBorder( + const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float lineWidth, const zIndex_t zIndex) { std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mGradientShader); }, [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); }, [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *mSolidShader); }, - [](const ACustomShaderBrush& ) {}, - }, brush); + [](const ACustomShaderBrush&) {}, + }, + brush); identityUv(); - //rect.insert(0, getVerticesForRect(x + 0.25f + lineWidth * 0.5f, y + 0.25f + lineWidth * 0.5f, width - (0.25f + lineWidth * 0.5f), height - (0.75f + lineWidth * 0.5f))); + // rect.insert(0, getVerticesForRect(x + 0.25f + lineWidth * 0.5f, y + 0.25f + lineWidth * 0.5f, width - (0.25f + + // lineWidth * 0.5f), height - (0.75f + lineWidth * 0.5f))); const float lineDelta = 0.25f + lineWidth / 2.f; float x = position.x; @@ -474,28 +477,25 @@ void OpenGLRenderer::renderRectangleBorder(const Cmd& cmd, const ABrush& brush, glm::vec3(glm::vec4 { x + lineDelta, y, 1, 1 }) }; - mBatchVao.insert(0, std::span{verticies}, "rectangleBorder"); + mBatchVao.insert(0, std::span { verticies }, "rectangleBorder"); glLineWidth(lineWidth); } -void OpenGLRenderer::renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& brush, - glm::vec2 position, - glm::vec2 size, - float radius, - int borderWidth, - const zIndex_t zIndex) { +void OpenGLRenderer::renderRoundedRectangleBorder( + const Cmd& cmd, const ABrush& brush, glm::vec2 position, glm::vec2 size, float radius, int borderWidth, + const zIndex_t zIndex) { std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mGradientShader); }, [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); }, [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *mRoundedSolidShaderBorder); }, - [](const ACustomShaderBrush& ) {}, - }, brush); + [](const ACustomShaderBrush&) {}, + }, + brush); identityUv(); - glm::vec2 innerSize = {size.x - borderWidth * 2, - size.y - borderWidth * 2}; + glm::vec2 innerSize = { size.x - borderWidth * 2, size.y - borderWidth * 2 }; gl::Program::currentShader()->set(aui::ShaderUniforms::OUTER_SIZE, 2.f * radius / size); gl::Program::currentShader()->set(aui::ShaderUniforms::INNER_SIZE, 2.f * (radius - borderWidth) / innerSize); @@ -503,13 +503,10 @@ void OpenGLRenderer::renderRoundedRectangleBorder(const Cmd& cmd, const ABrush& // appendRect(position, size, zIndex, cmd.transform); } -void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, - glm::vec2 size, - float blurRadius, - const AColor& color, - const zIndex_t zIndex) { - AUI_ASSERTX(blurRadius >= 0.f, - "blurRadius is expected to be non negative, use boxShadowInner for inset shadows instead"); +void OpenGLRenderer::renderBoxShadow( + const Cmd& cmd, glm::vec2 position, glm::vec2 size, float blurRadius, const AColor& color, const zIndex_t zIndex) { + AUI_ASSERTX( + blurRadius >= 0.f, "blurRadius is expected to be non negative, use boxShadowInner for inset shadows instead"); identityUv(); mBoxShadowShader->use(); mBoxShadowShader->set(aui::ShaderUniforms::SL_UNIFORM_SIGMA, blurRadius / 2.f); @@ -540,14 +537,9 @@ void OpenGLRenderer::renderBoxShadow(const Cmd& cmd, glm::vec2 position, // drawRectImpl(glm::vec2{x, y}, glm::vec2{w, h}, zIndex); } -void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, - glm::vec2 size, - float blurRadius, - float spreadRadius, - float borderRadius, - const AColor& color, - glm::vec2 offset, - const zIndex_t zIndex) { +void OpenGLRenderer::renderBoxShadowInner( + const Cmd& cmd, glm::vec2 position, glm::vec2 size, float blurRadius, float spreadRadius, float borderRadius, + const AColor& color, glm::vec2 offset, const zIndex_t zIndex) { AUI_ASSERTX(blurRadius >= 0.f, "blurRadius is expected to be non negative"); blurRadius *= -1.f; identityUv(); @@ -577,9 +569,7 @@ void OpenGLRenderer::renderBoxShadowInner(const Cmd& cmd, glm::vec2 position, // appendRect(glm::vec2{x, y}, glm::vec2{w, h}, zIndex, cmd.transform); } -void OpenGLRenderer::renderString(const Cmd& cmd, glm::vec2 position, - const AString& string, - const AFontStyle& fs) { +void OpenGLRenderer::renderString(const Cmd& cmd, glm::vec2 position, const AString& string, const AFontStyle& fs) { prerenderString(position, string, fs)->draw(); } @@ -639,20 +629,16 @@ class OpenGLPrerenderedString : public IRenderer::IPrerenderedString { OpenGLRenderer::FontEntryData* mEntryData; FontRendering mFontRendering; - OpenGLPrerenderedString(OpenGLRenderer* renderer, - gl::VertexBuffer vertexBuffer, - gl::IndexBuffer indexBuffer, - int textWidth, - int textHeight, - OpenGLRenderer::FontEntryData* entryData, - FontRendering fontRendering) : - mRenderer(renderer), - mVertexBuffer(std::move(vertexBuffer)), - mIndexBuffer(std::move(indexBuffer)), - mTextWidth(textWidth), - mTextHeight(textHeight), - mEntryData(entryData), - mFontRendering(fontRendering) { + OpenGLPrerenderedString( + OpenGLRenderer* renderer, gl::VertexBuffer vertexBuffer, gl::IndexBuffer indexBuffer, int textWidth, + int textHeight, OpenGLRenderer::FontEntryData* entryData, FontRendering fontRendering) + : mRenderer(renderer) + , mVertexBuffer(std::move(vertexBuffer)) + , mIndexBuffer(std::move(indexBuffer)) + , mTextWidth(textWidth) + , mTextHeight(textHeight) + , mEntryData(entryData) + , mFontRendering(fontRendering) { if (mRenderer->isVaoAvailable()) { mVao.emplace(); mVao->bind(); @@ -663,9 +649,9 @@ class OpenGLPrerenderedString : public IRenderer::IPrerenderedString { } } - void draw() override { - if (mIndexBuffer.count() == 0) return; + if (mIndexBuffer.count() == 0) + return; decltype(auto) img = mEntryData->texturePacker.getImage(); if (!img) @@ -673,7 +659,8 @@ class OpenGLPrerenderedString : public IRenderer::IPrerenderedString { if (AWindow::current()->profiling()->showBaseline) { mRenderer->rectangle( - ASolidBrush { AColor::RED.transparentize(0.5f) }, { 0, 0 }, std::numeric_limits::max(), { mTextWidth, 1 }); // debug baseline + ASolidBrush { AColor::RED.transparentize(0.5f) }, { 0, 0 }, std::numeric_limits::max(), + { mTextWidth, 1 }); // debug baseline } auto width = img->width(); @@ -720,23 +707,20 @@ class OpenGLPrerenderedString : public IRenderer::IPrerenderedString { } } - int getWidth() override { - return mTextWidth; - } + int getWidth() override { return mTextWidth; } - int getHeight() override { - return mTextHeight; - } + int getHeight() override { return mTextHeight; } private: static void setupVertexAttribs() { glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); - glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(OpenGLPrerenderedString::Vertex), - reinterpret_cast(0)); - glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof(OpenGLPrerenderedString::Vertex), - reinterpret_cast(sizeof(glm::vec2))); + glVertexAttribPointer( + 0, 2, GL_FLOAT, false, sizeof(OpenGLPrerenderedString::Vertex), reinterpret_cast(0)); + glVertexAttribPointer( + 1, 2, GL_FLOAT, false, sizeof(OpenGLPrerenderedString::Vertex), + reinterpret_cast(sizeof(glm::vec2))); } }; @@ -750,14 +734,12 @@ class OpenGLMultiStringCanvas : public IRenderer::IMultiStringCanvas { int mAdvanceY = 0; public: - OpenGLMultiStringCanvas(OpenGLRenderer* renderer, const AFontStyle& fontStyle) : - mRenderer(renderer), - mFontStyle(fontStyle), - mEntryData(renderer->getFontEntryData(fontStyle)) { + OpenGLMultiStringCanvas(OpenGLRenderer* renderer, const AFontStyle& fontStyle) + : mRenderer(renderer), mFontStyle(fontStyle), mEntryData(renderer->getFontEntryData(fontStyle)) { mVertices.reserve(1000); } - template + template void addStringT(const glm::ivec2& position, UnicodeString text) noexcept { mVertices.reserve(mVertices.capacity() + text.length() * 4); auto& font = mFontStyle.font; @@ -773,11 +755,11 @@ class OpenGLMultiStringCanvas : public IRenderer::IMultiStringCanvas { for (auto i = text.begin(); i != text.end(); ++i, ++counter) { AChar c = *i; if (c == ' ') { - notifySymbolAdded({glm::ivec2{advance, advanceY}}); + notifySymbolAdded({ glm::ivec2 { advance, advanceY } }); advance += mFontStyle.getSpaceWidth(); } else if (c == '\n') { - notifySymbolAdded({glm::ivec2{advance, advanceY}}); - advanceX = (glm::max)(advanceX, int(glm::ceil(advance))); + notifySymbolAdded({ glm::ivec2 { advance, advanceY } }); + advanceX = (glm::max) (advanceX, int(glm::ceil(advance))); advance = position.x; advanceY += mFontStyle.getLineHeight(); nextLine(); @@ -788,7 +770,6 @@ class OpenGLMultiStringCanvas : public IRenderer::IMultiStringCanvas { continue; } if ((advance >= 0 && advance <= 99999) /* || gui3d */) { - int posX = advance + ch.horizontal.bearing.x; int posY = advanceY - ch.horizontal.bearing.y; int width = ch.image->width(); @@ -804,23 +785,18 @@ class OpenGLMultiStringCanvas : public IRenderer::IMultiStringCanvas { uv.y += BIAS; uv.z -= BIAS; uv.w -= BIAS; - mRenderer->mCharData.push_back(OpenGLRenderer::CharacterData{uv}); + mRenderer->mCharData.push_back(OpenGLRenderer::CharacterData { uv }); ch.rendererData = &mRenderer->mCharData.last(); mEntryData->isTextureInvalid = true; } else { uv = reinterpret_cast(ch.rendererData)->uv; } - notifySymbolAdded({glm::ivec2{posX, posY}}); - mVertices.push_back({glm::vec2(posX, posY + height), - glm::vec2(uv.x, uv.w)}); - mVertices.push_back({glm::vec2(posX + width, posY + height), - glm::vec2(uv.z, uv.w)}); - mVertices.push_back({glm::vec2(posX, posY), - glm::vec2(uv.x, uv.y)}); - mVertices.push_back({glm::vec2(posX + width, posY), - glm::vec2(uv.z, uv.y)}); - + notifySymbolAdded({ glm::ivec2 { posX, posY } }); + mVertices.push_back({ glm::vec2(posX, posY + height), glm::vec2(uv.x, uv.w) }); + mVertices.push_back({ glm::vec2(posX + width, posY + height), glm::vec2(uv.z, uv.w) }); + mVertices.push_back({ glm::vec2(posX, posY), glm::vec2(uv.x, uv.y) }); + mVertices.push_back({ glm::vec2(posX + width, posY), glm::vec2(uv.z, uv.y) }); } if (hasKerning) { @@ -835,15 +811,13 @@ class OpenGLMultiStringCanvas : public IRenderer::IMultiStringCanvas { } } - notifySymbolAdded({glm::ivec2{advance, advanceY}}); + notifySymbolAdded({ glm::ivec2 { advance, advanceY } }); - mAdvanceX = (glm::max)(mAdvanceX, (glm::max)(advanceX, int(glm::ceil(advance)))); + mAdvanceX = (glm::max) (mAdvanceX, (glm::max) (advanceX, int(glm::ceil(advance)))); mAdvanceY = advanceY + mFontStyle.getLineHeight(); } - void addString(const glm::ivec2& position, AStringView text) noexcept override { - addStringT(position, text); - } + void addString(const glm::ivec2& position, AStringView text) noexcept override { addStringT(position, text); } void addString(const glm::ivec2& position, std::u32string_view text) noexcept override { addStringT(position, text); @@ -868,23 +842,19 @@ class OpenGLMultiStringCanvas : public IRenderer::IMultiStringCanvas { gl::IndexBuffer indexBuffer; indexBuffer.set(indices); - return _new(mRenderer, - std::move(vertexBuffer), - std::move(indexBuffer), - mAdvanceX, - mAdvanceY, - mEntryData, - mFontStyle.fontRendering); + return _new( + mRenderer, std::move(vertexBuffer), std::move(indexBuffer), mAdvanceX, mAdvanceY, mEntryData, + mFontStyle.fontRendering); } ~OpenGLMultiStringCanvas() override = default; }; -_ OpenGLRenderer::prerenderString(glm::vec2 position, - const AString& text, - const AFontStyle& fs) { +_ +OpenGLRenderer::prerenderString(glm::vec2 position, const AString& text, const AFontStyle& fs) { // ALOG_DEBUG("OpenGL") << "prerenderString: " << text; - if (text.empty()) return nullptr; + if (text.empty()) + return nullptr; OpenGLMultiStringCanvas c(this, fs); c.addString(position, text); @@ -904,17 +874,13 @@ OpenGLRenderer::FontEntryData* OpenGLRenderer::getFontEntryData(const AFontStyle return entryData; } -_unique OpenGLRenderer::createNewTexture() { - return std::make_unique(); -} +_unique OpenGLRenderer::createNewTexture() { return std::make_unique(); } _ OpenGLRenderer::newMultiStringCanvas(const AFontStyle& style) { return _new(this, style); } -bool OpenGLRenderer::isVaoAvailable() const noexcept { - return glBindVertexArray != nullptr; -} +bool OpenGLRenderer::isVaoAvailable() const noexcept { return glBindVertexArray != nullptr; } void OpenGLRenderer::renderPushMaskBefore() { glStencilFunc(GL_ALWAYS, 0, 0xff); @@ -949,9 +915,7 @@ bool OpenGLRenderer::setupLineShader(const Cmd& cmd, const ABrush& brush, const std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mGradientShader); }, - [&](const ATexturedBrush& brush) { - texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); - }, + [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); }, [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *mSolidShader); }, [](const ACustomShaderBrush&) {}, }, @@ -964,9 +928,7 @@ bool OpenGLRenderer::setupLineShader(const Cmd& cmd, const ABrush& brush, const std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mGradientShader); }, - [&](const ATexturedBrush& brush) { - texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); - }, + [&](const ATexturedBrush& brush) { texturedBrush(cmd, brush, *this, *mTexturedShader, mBatchVao); }, [&](const ASolidBrush& brush) { solidBrush(cmd, brush, *mLineSolidDashedShader); }, [](const ACustomShaderBrush&) {}, }, @@ -992,10 +954,12 @@ struct LineVertex { float distance; float unused; }; -} +} // namespace -void OpenGLRenderer::renderLines(const Cmd& cmd, const ABrush& brush, AArrayView points, const ABorderStyle& style, AMetric width) { - if (points.size() < 2) return; +void OpenGLRenderer::renderLines( + const Cmd& cmd, const ABrush& brush, AArrayView points, const ABorderStyle& style, AMetric width) { + if (points.size() < 2) + return; const auto widthPx = width.getValuePx(); bool computeDistances = setupLineShader(cmd, brush, style, widthPx); gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, cmd.transform); @@ -1003,25 +967,25 @@ void OpenGLRenderer::renderLines(const Cmd& cmd, const ABrush& brush, AArrayView mBatchVao.bind(); - AVector positions; positions.reserve(points.size()); - positions << LineVertex{points[0], 0.f, 1.f}; + positions << LineVertex { points[0], 0.f, 1.f }; float distanceAccumulator = 0.f; - for (const auto& point: points | ranges::views::drop(1)) { + for (const auto& point : points | ranges::views::drop(1)) { if (computeDistances) { distanceAccumulator += glm::distance(positions.last().position, point); } - positions << LineVertex{point, distanceAccumulator, 1.f}; + positions << LineVertex { point, distanceAccumulator, 1.f }; } - mBatchVao.insert(0, std::span{positions}, "lines"); + mBatchVao.insert(0, std::span { positions }, "lines"); mBatchVao.drawArrays(GL_LINE_STRIP, points.size()); } -void OpenGLRenderer::renderLines(const Cmd& cmd, const ABrush& brush, AArrayView> points, - const ABorderStyle& style, AMetric width) { +void OpenGLRenderer::renderLines( + const Cmd& cmd, const ABrush& brush, AArrayView> points, const ABorderStyle& style, + AMetric width) { const auto widthPx = width.getValuePx(); bool computeDistances = setupLineShader(cmd, brush, style, widthPx); gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, cmd.transform); @@ -1032,20 +996,12 @@ void OpenGLRenderer::renderLines(const Cmd& cmd, const ABrush& brush, AArrayView AVector positions; positions.reserve(points.size() * 2); - for (const auto& [p1, p2]: points) { - positions << LineVertex{ - p1, - 0.f, - 1.f - }; - positions << LineVertex{ - p2, - glm::distance(p1, p2), - 1.f - }; + for (const auto& [p1, p2] : points) { + positions << LineVertex { p1, 0.f, 1.f }; + positions << LineVertex { p2, glm::distance(p1, p2), 1.f }; } - mBatchVao.insert(0, std::span{positions}, "lines"); + mBatchVao.insert(0, std::span { positions }, "lines"); mBatchVao.drawArrays(GL_LINES, positions.size()); } @@ -1065,26 +1021,23 @@ void OpenGLRenderer::renderPoints(const Cmd& cmd, const ABrush& brush, AArrayVie const auto widthPx = size.getValuePx(); gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, cmd.transform); - #if AUI_PLATFORM_ANDROID || AUI_PLATFORM_IOS || AUI_PLATFORM_EMSCRIPTEN // TODO slow, use instancing instead - for (auto point : points) { - drawRectImpl(point - glm::vec2(widthPx / 2), glm::vec2(widthPx), cmd.transform); - } + for (auto point : points) { + drawRectImpl(point - glm::vec2(widthPx / 2), glm::vec2(widthPx), cmd.transform); + } #else glPointSize(widthPx); mBatchVao.bind(); - mBatchVao.insert(0, std::span{points}, "lines"); + mBatchVao.insert(0, std::span { points }, "lines"); mBatchVao.drawArrays(GL_POINTS, points.size()); #endif } -void OpenGLRenderer::renderSquareSector(const Cmd& cmd, const ABrush& brush, - const glm::vec2& position, - const glm::vec2& size, - AAngleRadians begin, - AAngleRadians end) { +void OpenGLRenderer::renderSquareSector( + const Cmd& cmd, const ABrush& brush, const glm::vec2& position, const glm::vec2& size, AAngleRadians begin, + AAngleRadians end) { std::visit( aui::lambda_overloaded { [&](const ALinearGradientBrush& brush) { gradientBrush(cmd, brush, *mGradientShader); }, @@ -1096,11 +1049,9 @@ void OpenGLRenderer::renderSquareSector(const Cmd& cmd, const ABrush& brush, gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, cmd.transform); auto calculateLineMatrix = [](AAngleRadians angle) { - auto s = glm::sin(angle.radians()); - auto c = glm::cos(angle.radians()); - return glm::mat3{c, 0, 0, - s, 0, 0, - -0.5f * (s + c), 0, 0}; + auto s = glm::sin(angle.radians()); + auto c = glm::cos(angle.radians()); + return glm::mat3 { c, 0, 0, s, 0, 0, -0.5f * (s + c), 0, 0 }; }; auto m1 = calculateLineMatrix(begin + 180_deg); auto m2 = calculateLineMatrix(end); @@ -1113,7 +1064,6 @@ void OpenGLRenderer::renderSquareSector(const Cmd& cmd, const ABrush& brush, // appendRect(position, size, 0, cmd.transform); } - static void resetStencil() { glStencilMask(0xff); glClearStencil(0); @@ -1130,10 +1080,9 @@ void OpenGLRenderer::beginPaint(glm::uvec2 windowSize) { gl::State::bindVertexArray(0); gl::State::useProgram(0); - glDisable(GL_CULL_FACE); glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); setBlending(Blending::NORMAL); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -1148,7 +1097,6 @@ void OpenGLRenderer::endPaint() { gl::State::useProgram(0); } - void OpenGLRenderer::bindTemporaryVao() const noexcept { if (!isVaoAvailable()) { return; @@ -1167,11 +1115,15 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept public: explicit OpenGLRenderViewToTexture(OpenGLRenderer& renderer) : mRenderer(renderer) { auto prevFramebuffer = gl::Framebuffer::current(); - AUI_DEFER { AUI_NULLSAFE(prevFramebuffer)->bind(); else gl::Framebuffer::unbind(); }; + AUI_DEFER { + AUI_NULLSAFE(prevFramebuffer)->bind(); + else gl::Framebuffer::unbind(); + }; mFramebuffer.setSupersamplingRatio(1); - mFramebuffer.resize({1, 1}); - auto albedo = _new>(); + mFramebuffer.resize({ 1, 1 }); + auto albedo = _new< + gl::TextureRenderTarget>(); mFramebuffer.attach(albedo, GL_COLOR_ATTACHMENT0); albedo->texture().setupClampToEdge(); albedo->texture().setupNearest(); @@ -1179,11 +1131,14 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept } static gl::Framebuffer* getMainRenderingFramebuffer(IRenderer& renderer) { - return dynamic_cast(renderer.getWindow()->getRenderingContext().get())->framebuffer().valueOr(nullptr); + return dynamic_cast(renderer.getWindow()->getRenderingContext().get()) + ->framebuffer() + .valueOr(nullptr); } - bool begin(IRenderer& renderer, glm::ivec2 surfaceSize, IRenderViewToTexture::InvalidArea& invalidArea) override { - AUI_ASSERT(!invalidArea.empty()); // if invalid areas are empty, what should we redraw then? + bool begin( + IRenderer& renderer, glm::ivec2 surfaceSize, IRenderViewToTexture::InvalidArea& invalidArea) override { + AUI_ASSERT(!invalidArea.empty()); // if invalid areas are empty, what should we redraw then? AUI_ASSERT(&mRenderer == &renderer); auto mainRenderingFB = getMainRenderingFramebuffer(renderer); AUI_ASSERT(mainRenderingFB != nullptr); @@ -1203,8 +1158,8 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept mFramebuffer.resize(surfaceSize); if (prevSize != mFramebuffer.size()) [[unlikely]] { // switching to full redraw - we have lost previous data. - invalidArea = InvalidArea::Full{}; - return true; // omit partial update checks + invalidArea = InvalidArea::Full {}; + return true; // omit partial update checks } } @@ -1216,9 +1171,11 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept mainRenderingFB->bindForWrite(); const auto supersampledRenderingFBSize = mFramebuffer.size() * mainRenderingFB->supersamlingRatio(); - glBlitFramebuffer(0, 0, mFramebuffer.size().x, mFramebuffer.size().y, - 0, mainRenderingFB->supersampledSize().y - supersampledRenderingFBSize.y, supersampledRenderingFBSize.x, mainRenderingFB->supersampledSize().y, - GL_COLOR_BUFFER_BIT, GL_NEAREST); + glBlitFramebuffer( + 0, 0, mFramebuffer.size().x, mFramebuffer.size().y, 0, + mainRenderingFB->supersampledSize().y - supersampledRenderingFBSize.y, + supersampledRenderingFBSize.x, mainRenderingFB->supersampledSize().y, GL_COLOR_BUFFER_BIT, + GL_NEAREST); } // 2. mark invalidated rectangles with stencil mask. @@ -1229,35 +1186,34 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept // pixels. glDisable(GL_BLEND); AUI_DEFER { - glEnable(GL_BLEND); - glStencilMask(0x00); - glStencilFunc(GL_EQUAL, ++mRenderer.mStencilDepth, 0xff); + glEnable(GL_BLEND); + glStencilMask(0x00); + glStencilFunc(GL_EQUAL, ++mRenderer.mStencilDepth, 0xff); }; static constexpr auto MAX_RECTANGLE_COUNT = std::decay_t::capacity(); using Vertices = AStaticVector; using Indices = AStaticVector; - auto vertices = ranges::views::transform(*rectangles, [&](const ARect& r) { - return getVerticesForRect(r.p1, r.size()); - }) | ranges::views::join | ranges::to(); + auto vertices = + ranges::views::transform( + *rectangles, [&](const ARect& r) { return getVerticesForRect(r.p1, r.size()); }) | + ranges::views::join | ranges::to(); mRenderer.mBatchVao.insert(0, std::span(vertices), "render-to-texture invalid areas"); - auto indices = ranges::views::generate([i = 0]() mutable { - int offset = 4 * i++; - return std::array{GLuint(offset + 0), - GLuint(offset + 1), - GLuint(offset + 2), - GLuint(offset + 2), - GLuint(offset + 1), - GLuint(offset + 3)}; - }) | ranges::views::take_exactly(rectangles->size()) - | ranges::views::join - | ranges::to() - ; + auto indices = + ranges::views::generate([i = 0]() mutable { + int offset = 4 * i++; + return std::array { + GLuint(offset + 0), GLuint(offset + 1), GLuint(offset + 2), + GLuint(offset + 2), GLuint(offset + 1), GLuint(offset + 3) + }; + }) | + ranges::views::take_exactly(rectangles->size()) | ranges::views::join | ranges::to(); static constexpr auto DEFAULT_INDICES_SIZE = 6; - if (indices.size() != DEFAULT_INDICES_SIZE) mRenderer.mBatchVao.indices(std::span{indices}); + if (indices.size() != DEFAULT_INDICES_SIZE) + mRenderer.mBatchVao.indices(std::span { indices }); AUI_DEFER { - if (indices.size() != DEFAULT_INDICES_SIZE) { - mRenderer.mBatchVao.indices(std::span{indices.data(),6 }); - } + if (indices.size() != DEFAULT_INDICES_SIZE) { + mRenderer.mBatchVao.indices(std::span { indices.data(), 6 }); + } }; mRenderer.mSolidShader->use(); // mRenderer.uploadToShaderCommon(); // TODO @@ -1275,13 +1231,13 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept auto mainRenderingFB = gl::Framebuffer::current(); AUI_ASSERT(mainRenderingFB != nullptr); AUI_DEFER { - mainRenderingFB->bind(); - glStencilMask(0xff); - glClearColor(0, 0, 0, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glStencilFunc(GL_EQUAL, 0x00, 0xff); - glStencilMask(0); - mRenderer.setStencilDepth(0); + mainRenderingFB->bind(); + glStencilMask(0xff); + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glStencilFunc(GL_EQUAL, 0x00, 0xff); + glStencilMask(0); + mRenderer.setStencilDepth(0); }; // copy render results from mainRenderingFB (main render buffer) to our texture render target. @@ -1289,8 +1245,10 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept mainRenderingFB->bindForRead(); mFramebuffer.bindForWrite(); const auto supersampledRenderingFBSize = mFramebuffer.size() * mainRenderingFB->supersamlingRatio(); - glBlitFramebuffer(0, mainRenderingFB->supersampledSize().y - supersampledRenderingFBSize.y, supersampledRenderingFBSize.x, mainRenderingFB->supersampledSize().y, - 0, 0, mFramebuffer.size().x, mFramebuffer.size().y, GL_COLOR_BUFFER_BIT, GL_LINEAR); + glBlitFramebuffer( + 0, mainRenderingFB->supersampledSize().y - supersampledRenderingFBSize.y, + supersampledRenderingFBSize.x, mainRenderingFB->supersampledSize().y, 0, 0, mFramebuffer.size().x, + mFramebuffer.size().y, GL_COLOR_BUFFER_BIT, GL_LINEAR); } void draw(IRenderer& renderer) override { @@ -1301,13 +1259,8 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept mRenderer.identityUv(); // mRenderer.uploadToShaderCommon(); // TODO - const glm::vec2 uvs[] = { - {0, 0}, - {1, 0}, - {0, 1}, - {1, 1} - }; - mRenderer.mBatchVao.insertIfKeyMismatches(1, std::span{uvs}, "OpenGLRenderViewToTexture"); + const glm::vec2 uvs[] = { { 0, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } }; + mRenderer.mBatchVao.insertIfKeyMismatches(1, std::span { uvs }, "OpenGLRenderViewToTexture"); // mRenderer.drawRectImpl({0, 0}, mFramebuffer.size()); if (auto& p = AWindow::current()->profiling(); p && p->renderToTextureDecay) [[unlikely]] { // decays to fast. attach it to time @@ -1324,12 +1277,12 @@ _unique OpenGLRenderer::newRenderViewToTexture() noexcept auto mainRenderingFB = gl::Framebuffer::current(); AUI_ASSERT(mainRenderingFB != nullptr); AUI_DEFER { - // restore. - glColorMask(true, true, true, true); - mainRenderingFB->bind(); - glEnable(GL_STENCIL_TEST); - glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - renderer.setStencilDepth(0); + // restore. + glColorMask(true, true, true, true); + mainRenderingFB->bind(); + glEnable(GL_STENCIL_TEST); + glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + renderer.setStencilDepth(0); }; mFramebuffer.bind(); glDisable(GL_STENCIL_TEST); @@ -1376,45 +1329,45 @@ void OpenGLRenderer::backdrops(glm::ivec2 position, glm::ivec2 size, std::span areaOfInterest; - auto initAreaOfInterestIfEmpty = [&](glm::ivec2 fbSize){ - if (areaOfInterest) { - return; - } - - auto fb = getFramebufferForMultiPassEffect(fbSize); - AUI_ASSERT(glm::all(glm::lessThanEqual(glm::u32vec2(fbSize), fb->framebuffer.size()))); - source->bindForRead(); - fb->framebuffer.bindForWrite(); - - auto vertices = getVerticesForRect(position, size); - std::array transformedVertices{}; - for (size_t i = 0; i < vertices.size(); ++i) { - auto ndc = glm::vec2(mTransform * glm::vec4(vertices[i], 0, 1)); - transformedVertices[i] = glm::ivec2((ndc + 1.f) / 2.f * glm::vec2(source->supersampledSize())); - } - - auto p1 = transformedVertices.front(); - auto p2 = transformedVertices.back(); - glBlitFramebuffer(p1.x, p1.y, p2.x, p2.y, 0, 0, fbSize.x, fbSize.y, GL_COLOR_BUFFER_BIT, GL_LINEAR); - areaOfInterest = AreaOfInterest{ - .framebuffer = std::move(fb), - .size = fbSize, - }; + auto initAreaOfInterestIfEmpty = [&](glm::ivec2 fbSize) { + if (areaOfInterest) { + return; + } + + auto fb = getFramebufferForMultiPassEffect(fbSize); + AUI_ASSERT(glm::all(glm::lessThanEqual(glm::u32vec2(fbSize), fb->framebuffer.size()))); + source->bindForRead(); + fb->framebuffer.bindForWrite(); + + auto vertices = getVerticesForRect(position, size); + std::array transformedVertices {}; + for (size_t i = 0; i < vertices.size(); ++i) { + auto ndc = glm::vec2(mTransform * glm::vec4(vertices[i], 0, 1)); + transformedVertices[i] = glm::ivec2((ndc + 1.f) / 2.f * glm::vec2(source->supersampledSize())); + } + + auto p1 = transformedVertices.front(); + auto p2 = transformedVertices.back(); + glBlitFramebuffer(p1.x, p1.y, p2.x, p2.y, 0, 0, fbSize.x, fbSize.y, GL_COLOR_BUFFER_BIT, GL_LINEAR); + areaOfInterest = AreaOfInterest { + .framebuffer = std::move(fb), + .size = fbSize, + }; }; { glDisable(GL_STENCIL_TEST); AUI_DEFER { - source->bind(); - source->bindViewport(); - glEnable(GL_STENCIL_TEST); + source->bind(); + source->bindViewport(); + glEnable(GL_STENCIL_TEST); }; for (const auto& backdrop : backdrops) { RenderHints::PushState s(*this); std::visit( aui::lambda_overloaded { - [&](const ass::Backdrop::LiquidFluid& liquidFluid) { + [&](const ass::Backdrop::LiquidFluid& liquidFluid) { if (areaOfInterest) { throw AException("LiquidGlass must be the first effect in backdrop list."); } @@ -1443,7 +1396,7 @@ void OpenGLRenderer::backdrops(glm::ivec2 position, glm::ivec2 size, std::spanbind(1); areaOfInterest->framebuffer->rendertarget->texture().setupNearest(); -// areaOfInterest->framebuffer->rendertarget->texture().setupMirroredRepeat(); + // areaOfInterest->framebuffer->rendertarget->texture().setupMirroredRepeat(); areaOfInterest->framebuffer->rendertarget->texture().setupClampToEdge(); auto offscreen1 = getFramebufferForMultiPassEffect(size); @@ -1451,12 +1404,12 @@ void OpenGLRenderer::backdrops(glm::ivec2 position, glm::ivec2 size, std::spanframebuffer.bindViewport(); static auto shader = [&] { - auto shader = std::make_unique(); + auto shader = std::make_unique(); - // shader->loadVertexShader( - // std::string(aui::sl_gen::basic_uv::vsh::glsl120::Shader::code())); - shader->loadFragmentShader( - R"( + // shader->loadVertexShader( + // std::string(aui::sl_gen::basic_uv::vsh::glsl120::Shader::code())); + shader->loadFragmentShader( + R"( precision highp float; precision highp int; varying vec4 SL_inter_vertex; @@ -1475,12 +1428,12 @@ void main() { } )"); - // aui::sl_gen::basic_uv::vsh::glsl120::Shader::setup(shader->handle()); - shader->compile(); - shader->use(); - shader->set(gl::Program::Uniform("uvmap"), 1); + // aui::sl_gen::basic_uv::vsh::glsl120::Shader::setup(shader->handle()); + shader->compile(); + shader->use(); + shader->set(gl::Program::Uniform("uvmap"), 1); - return shader; + return shader; }(); if (!shader) { @@ -1498,12 +1451,15 @@ void main() { shader->set(aui::ShaderUniforms::M2, m); // source framebuffer is slightly smaller than the framebuffer in area of interest, adjust it - shader->set(aui::ShaderUniforms::UV_SCALE, glm::vec2(areaOfInterest->size) / glm::vec2(areaOfInterest->framebuffer->framebuffer.size())); + shader->set( + aui::ShaderUniforms::UV_SCALE, + glm::vec2(areaOfInterest->size) / + glm::vec2(areaOfInterest->framebuffer->framebuffer.size())); } setTransformForced(glm::ortho( - 0.0f, static_cast(offscreen1->framebuffer.size().x) - 0.0f, - 0.f, static_cast(offscreen1->framebuffer.size().y) - 0.0f, -1.f, 1.f)); + 0.0f, static_cast(offscreen1->framebuffer.size().x) - 0.0f, 0.f, + static_cast(offscreen1->framebuffer.size().y) - 0.0f, -1.f, 1.f)); gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, mTransform); identityUv(); @@ -1516,8 +1472,8 @@ void main() { .framebuffer = std::move(offscreen1), .size = size, }; - }, - [&](const ass::Backdrop::GaussianBlurCustom& gaussianBlur) { + }, + [&](const ass::Backdrop::GaussianBlurCustom& gaussianBlur) { const auto radius = int(gaussianBlur.radius.getValuePx()); if (radius <= 1) { return; @@ -1536,25 +1492,24 @@ void main() { offscreen1->framebuffer.bindViewport(); setTransformForced(glm::ortho( - 0.0f, static_cast(offscreen1->framebuffer.size().x) - 0.0f, - 0.f, static_cast(offscreen1->framebuffer.size().y) - 0.0f, -1.f, 1.f)); + 0.0f, static_cast(offscreen1->framebuffer.size().x) - 0.0f, 0.f, + static_cast(offscreen1->framebuffer.size().y) - 0.0f, -1.f, 1.f)); struct BlurShaders { std::unique_ptr shader; }; static AUnorderedMap blurShaders; auto& blurShader = blurShaders.getOrInsert(radius, [&] { - BlurShaders result { - .shader = std::make_unique(), - }; + BlurShaders result { + .shader = std::make_unique(), + }; - auto kernel = aui::detail::gaussianKernel(radius); + auto kernel = aui::detail::gaussianKernel(radius); - // result.shader->loadVertexShader( - // std::string(aui::sl_gen::basic_uv::vsh::glsl120::Shader::code())); - result.shader->loadFragmentShader( - fmt::format( - R"( + // result.shader->loadVertexShader( + // std::string(aui::sl_gen::basic_uv::vsh::glsl120::Shader::code())); + result.shader->loadFragmentShader(fmt::format( + R"( precision highp float; precision highp int; varying vec2 SL_inter_uv; @@ -1575,15 +1530,14 @@ void main() {{ gl_FragColor = vec4(accumulator, 1.0); }} )", - fmt::arg("radius", radius), - fmt::arg("kernel_size", kernel.size()))); + fmt::arg("radius", radius), fmt::arg("kernel_size", kernel.size()))); - // aui::sl_gen::basic_uv::vsh::glsl120::Shader::setup(result.shader->handle()); - result.shader->compile(); - result.shader->use(); - result.shader->setArray(aui::ShaderUniforms::KERNEL, kernel); + // aui::sl_gen::basic_uv::vsh::glsl120::Shader::setup(result.shader->handle()); + result.shader->compile(); + result.shader->use(); + result.shader->setArray(aui::ShaderUniforms::KERNEL, kernel); - return result; + return result; }); if (!blurShader.shader) { @@ -1593,13 +1547,14 @@ void main() {{ blurShader.shader->use(); { - auto stepSize = glm::vec2(1.f / areaOfInterest->framebuffer->framebuffer.supersampledSize().x, 0.f); + auto stepSize = + glm::vec2(1.f / areaOfInterest->framebuffer->framebuffer.supersampledSize().x, 0.f); blurShader.shader->set(aui::ShaderUniforms::PIXEL_TO_UV, stepSize); blurShader.shader->set( aui::ShaderUniforms::M2, glm::vec2(areaOfInterest->size) / - glm::vec2(areaOfInterest->framebuffer->framebuffer.supersampledSize()) - - stepSize / 2.f /* small bias to avoid dirty edges */); + glm::vec2(areaOfInterest->framebuffer->framebuffer.supersampledSize()) - + stepSize / 2.f /* small bias to avoid dirty edges */); } gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, mTransform); identityUv(); @@ -1614,8 +1569,8 @@ void main() {{ offscreen2->framebuffer.bindViewport(); setTransformForced(glm::ortho( - 0.0f, static_cast(offscreen2->framebuffer.size().x) - 0.0f, - 0.f, static_cast(offscreen2->framebuffer.size().y) - 0.0f, -1.f, 1.f)); + 0.0f, static_cast(offscreen2->framebuffer.size().x) - 0.0f, 0.f, + static_cast(offscreen2->framebuffer.size().y) - 0.0f, -1.f, 1.f)); blurShader.shader->set(aui::ShaderUniforms::M1, glm::vec2(0.0)); @@ -1625,7 +1580,7 @@ void main() {{ blurShader.shader->set( aui::ShaderUniforms::M2, glm::vec2(sizeDownscaled) / glm::vec2(offscreen1->framebuffer.supersampledSize()) - - stepSize / 2.f); + stepSize / 2.f); } gl::Program::currentShader()->set(aui::ShaderUniforms::TRANSFORM, mTransform); // TODO: replace 0 with zIndex and add transform, then uncomment @@ -1635,7 +1590,7 @@ void main() {{ .framebuffer = std::move(offscreen2), .size = sizeDownscaled, }; - }, + }, }, backdrop); } @@ -1649,12 +1604,12 @@ void main() {{ glm::vec2(areaOfInterest->size - 1 /* small bias to avoid dirty edges */) / glm::vec2(areaOfInterest->framebuffer->framebuffer.supersampledSize()); const glm::vec2 uvs[] = { - { 0, 0}, + { 0, 0 }, { uv.x, 0 }, - { 0, uv.y }, + { 0, uv.y }, { uv.x, uv.y }, }; - mBatchVao.insertIfKeyMismatches(1, std::span{uvs}, "backdrops"); + mBatchVao.insertIfKeyMismatches(1, std::span { uvs }, "backdrops"); } auto& texture = areaOfInterest->framebuffer->rendertarget->texture(); @@ -1681,38 +1636,39 @@ OpenGLRenderer::FramebufferFromPool OpenGLRenderer::getFramebufferForMultiPassEf return aui::ptr::manage_unique( [&]() -> FramebufferWithTextureRT* { - auto applicableSizeOnly = - mFramebuffersForMultiPassEffectsPool | ranges::views::filter([&](const auto& fb) { - return glm::all(glm::greaterThanEqual(fb->framebuffer.size(), minRequiredSize)); - }); - auto smallestFb = [](ranges::range auto& rng) { - return ranges::min_element(rng, std::less<> {}, [](const auto& fb) { - return fb->framebuffer.size().x * fb->framebuffer.size().y; - }); - }; - - auto release = [&](OffscreenFramebufferPool::iterator it) { - auto object = std::exchange(*it, {}); - mFramebuffersForMultiPassEffectsPool.erase(it); - return object.release(); - }; - - if (auto it = smallestFb(applicableSizeOnly); it != applicableSizeOnly.end()) { - return release(it.base()); - } + auto applicableSizeOnly = + mFramebuffersForMultiPassEffectsPool | ranges::views::filter([&](const auto& fb) { + return glm::all(glm::greaterThanEqual(fb->framebuffer.size(), minRequiredSize)); + }); + auto smallestFb = [](ranges::range auto& rng) { + return ranges::min_element(rng, std::less<> {}, [](const auto& fb) { + return fb->framebuffer.size().x * fb->framebuffer.size().y; + }); + }; + + auto release = [&](OffscreenFramebufferPool::iterator it) { + auto object = std::exchange(*it, {}); + mFramebuffersForMultiPassEffectsPool.erase(it); + return object.release(); + }; + + if (auto it = smallestFb(applicableSizeOnly); it != applicableSizeOnly.end()) { + return release(it.base()); + } - if (auto it = smallestFb(mFramebuffersForMultiPassEffectsPool); - it != mFramebuffersForMultiPassEffectsPool.end()) { - (*it)->framebuffer.resize(glm::max((*it)->framebuffer.size(), minRequiredSize)); - return release(it); - } + if (auto it = smallestFb(mFramebuffersForMultiPassEffectsPool); + it != mFramebuffersForMultiPassEffectsPool.end()) { + (*it)->framebuffer.resize(glm::max((*it)->framebuffer.size(), minRequiredSize)); + return release(it); + } - auto object = std::make_unique(); - object->framebuffer.resize(minRequiredSize); - object->rendertarget = _new>(); - object->framebuffer.attach(object->rendertarget, GL_COLOR_ATTACHMENT0); + auto object = std::make_unique(); + object->framebuffer.resize(minRequiredSize); + object->rendertarget = + _new>(); + object->framebuffer.attach(object->rendertarget, GL_COLOR_ATTACHMENT0); - return object.release(); + return object.release(); }(), FramebufferBackToPool { this }); } diff --git a/aui.views/src/AUI/GL/OpenGLRenderer.h b/aui.views/src/AUI/GL/OpenGLRenderer.h index ef1280a72..3c005d4da 100644 --- a/aui.views/src/AUI/GL/OpenGLRenderer.h +++ b/aui.views/src/AUI/GL/OpenGLRenderer.h @@ -137,13 +137,13 @@ friend class OpenGLMultiStringCanvas; static constexpr size_t Z_DEPTH = 1000; template - void appendRect(const glm::vec2 position, const glm::vec2 size, const zIndex_t zIndex, const glm::mat4 transform, T additionalData) { + void appendRect(const glm::vec2 position, const glm::vec2 size, const glm::mat4 transform, T additionalData) { static_assert(std::is_trivially_copyable_v); float x = position.x; float y = position.y; float w = x + size.x; float h = y + size.y; - float z = -1.f + zIndex * (1. / Z_DEPTH); + float z = -1.f; std::array verticies { glm::vec3 { x, h, z }, diff --git a/aui.views/src/AUI/View/AView.cpp b/aui.views/src/AUI/View/AView.cpp index b73e0e60e..7d84f69c2 100644 --- a/aui.views/src/AUI/View/AView.cpp +++ b/aui.views/src/AUI/View/AView.cpp @@ -514,12 +514,13 @@ void AView::setPosition(glm::ivec2 position) { redraw(); emit mPositionChanged(position); } -void AView::setZIndex(zIndex_t zIndex) { +void AView::setZIndex(const zIndex_t value) { mSkipUntilLayoutUpdate = false; - mZIndex = zIndex; + mZIndex = value; redraw(); - emit mZIndexChanged(zIndex); + emit mZIndexChanged(value); } + void AView::setSize(glm::ivec2 size) { mMarkedMinContentSizeInvalid = false; diff --git a/aui.views/src/AUI/View/AView.h b/aui.views/src/AUI/View/AView.h index 9c154e2fd..99f83c8fd 100644 --- a/aui.views/src/AUI/View/AView.h +++ b/aui.views/src/AUI/View/AView.h @@ -592,7 +592,7 @@ class API_AUI_VIEWS AView: public AObject virtual void setPosition(glm::ivec2 position); - void setZIndex(zIndex_t zIndex); + virtual void setZIndex(const zIndex_t value); /** * Set size ignoring all restrictions (i.e. min size, max size, fixed size, etc...). Used by AAnimator. diff --git a/aui.views/src/AUI/View/AViewContainerBase.cpp b/aui.views/src/AUI/View/AViewContainerBase.cpp index 4eddf4b17..ec04aa86b 100644 --- a/aui.views/src/AUI/View/AViewContainerBase.cpp +++ b/aui.views/src/AUI/View/AViewContainerBase.cpp @@ -636,6 +636,14 @@ void AViewContainerBase::setEnabled(bool enabled) { notifyParentEnabledStateChanged(enabled); } +void AViewContainerBase::setZIndex(zIndex_t value) { + AView::setZIndex(value); + + for (auto& child : mViews) { + child->setZIndex(value + 1); + } +} + void AViewContainerBase::notifyParentEnabledStateChanged(bool enabled) { enabled &= mDirectlyEnabled; AView::notifyParentEnabledStateChanged(enabled); diff --git a/aui.views/src/AUI/View/AViewContainerBase.h b/aui.views/src/AUI/View/AViewContainerBase.h index 1a7c8d460..0b61748a9 100644 --- a/aui.views/src/AUI/View/AViewContainerBase.h +++ b/aui.views/src/AUI/View/AViewContainerBase.h @@ -116,6 +116,8 @@ class API_AUI_VIEWS AViewContainerBase : public AView { void setEnabled(bool enabled = true) override; + void setZIndex(const zIndex_t value) override; + auto begin() const { return mViews.cbegin(); }