From 240a10faf39ff111fd6f9ccf4d1e9ef28d42e908 Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Wed, 1 Jan 2025 16:06:05 -0500 Subject: [PATCH 01/14] add gui stencil mask for presenter class --- libopenage/presenter/presenter.cpp | 41 ++++++++++++++++++++++++++++-- libopenage/presenter/presenter.h | 4 +++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/libopenage/presenter/presenter.cpp b/libopenage/presenter/presenter.cpp index 9775b62d9b..b90c2f33fb 100644 --- a/libopenage/presenter/presenter.cpp +++ b/libopenage/presenter/presenter.cpp @@ -20,6 +20,8 @@ #include "renderer/camera/camera.h" #include "renderer/gui/gui.h" #include "renderer/gui/integration/public/gui_application_with_logger.h" +#include "renderer/opengl/context.h" +#include "renderer/opengl/lookup.h" #include "renderer/render_factory.h" #include "renderer/render_pass.h" #include "renderer/render_target.h" @@ -307,17 +309,52 @@ void Presenter::init_final_render_pass() { }); } +void Presenter::enable_stencil_for_gui_mask() { + glEnable(GL_STENCIL_TEST); + glClear(GL_STENCIL_BUFFER_BIT); + // Replace stencil value with 1 when depth test passes + glStencilFunc(GL_ALWAYS, 1, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilMask(0xFF); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); +} + +void Presenter::enable_stencil_for_world() { + // Only pass if stencil value is not 1 + glStencilFunc(GL_NOTEQUAL, 1, 0xFF); + glStencilMask(0x00); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); +} + +void Presenter::disable_stencil() { + glDisable(GL_STENCIL_TEST); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); +} + void Presenter::render() { // TODO: Pass current time to update() instead of fetching it in renderer this->camera_manager->update(); this->terrain_renderer->update(); this->world_renderer->update(); this->hud_renderer->update(); + + // First Pass: Render GUI to stencil buffer + this->enable_stencil_for_gui_mask(); this->gui->render(); - for (auto &pass : this->render_passes) { - this->renderer->render(pass); + // Second Pass: Render game world with stencil buffer + this->enable_stencil_for_world(); + for (size_t i = 0; i < this->render_passes.size() - 2; ++i) { + this->renderer->render(this->render_passes[i]); } + + // Third Pass: Render GUI to screen + this->disable_stencil(); + this->gui->render(); + this->renderer->render(this->render_passes[this->render_passes.size() - 2]); + + // Fourth Pass: Render screen to window + this->renderer->render(this->render_passes.back()); } } // namespace openage::presenter diff --git a/libopenage/presenter/presenter.h b/libopenage/presenter/presenter.h index 2059daeed0..97f6a1934e 100644 --- a/libopenage/presenter/presenter.h +++ b/libopenage/presenter/presenter.h @@ -142,6 +142,10 @@ class Presenter { // void init_audio(); + void enable_stencil_for_gui_mask(); + void enable_stencil_for_world(); + void disable_stencil(); + /** * Render all configured render passes in sequence. */ From 2622849de3d392ec1249e66bdc91fec76a8b18e7 Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Sun, 5 Jan 2025 17:26:54 -0500 Subject: [PATCH 02/14] refactor by add init_stencil() --- libopenage/presenter/presenter.cpp | 11 ++++++++--- libopenage/presenter/presenter.h | 3 ++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/libopenage/presenter/presenter.cpp b/libopenage/presenter/presenter.cpp index b90c2f33fb..ba81b83687 100644 --- a/libopenage/presenter/presenter.cpp +++ b/libopenage/presenter/presenter.cpp @@ -1,4 +1,4 @@ -// Copyright 2019-2024 the openage authors. See copying.md for legal info. +// Copyright 2019-2025 the openage authors. See copying.md for legal info. #include "presenter.h" @@ -309,12 +309,15 @@ void Presenter::init_final_render_pass() { }); } -void Presenter::enable_stencil_for_gui_mask() { +void Presenter::init_stencil_test() { glEnable(GL_STENCIL_TEST); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glClear(GL_STENCIL_BUFFER_BIT); +} + +void Presenter::enable_stencil_for_gui_mask() { // Replace stencil value with 1 when depth test passes glStencilFunc(GL_ALWAYS, 1, 0xFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); glStencilMask(0xFF); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); } @@ -338,6 +341,8 @@ void Presenter::render() { this->world_renderer->update(); this->hud_renderer->update(); + this->init_stencil_test(); + // First Pass: Render GUI to stencil buffer this->enable_stencil_for_gui_mask(); this->gui->render(); diff --git a/libopenage/presenter/presenter.h b/libopenage/presenter/presenter.h index 97f6a1934e..7bd4112929 100644 --- a/libopenage/presenter/presenter.h +++ b/libopenage/presenter/presenter.h @@ -1,4 +1,4 @@ -// Copyright 2019-2024 the openage authors. See copying.md for legal info. +// Copyright 2019-2025 the openage authors. See copying.md for legal info. #pragma once @@ -142,6 +142,7 @@ class Presenter { // void init_audio(); + void init_stencil_test(); void enable_stencil_for_gui_mask(); void enable_stencil_for_world(); void disable_stencil(); From 18622d4241aebfb0a43053743495f6a08cccbb32 Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Sat, 18 Jan 2025 15:56:31 -0500 Subject: [PATCH 03/14] implement stencil test in Level1 and integrate it in render pass --- libopenage/presenter/presenter.cpp | 57 ++++++++----------------- libopenage/presenter/presenter.h | 12 +++--- libopenage/renderer/gui/gui.cpp | 8 ++++ libopenage/renderer/gui/gui.h | 12 ++++++ libopenage/renderer/opengl/renderer.cpp | 45 ++++++++++++++++++- libopenage/renderer/opengl/renderer.h | 6 +++ libopenage/renderer/render_pass.cpp | 14 ++++-- libopenage/renderer/render_pass.h | 31 ++++++++++++-- 8 files changed, 132 insertions(+), 53 deletions(-) diff --git a/libopenage/presenter/presenter.cpp b/libopenage/presenter/presenter.cpp index ba81b83687..c1ac699f68 100644 --- a/libopenage/presenter/presenter.cpp +++ b/libopenage/presenter/presenter.cpp @@ -20,8 +20,6 @@ #include "renderer/camera/camera.h" #include "renderer/gui/gui.h" #include "renderer/gui/integration/public/gui_application_with_logger.h" -#include "renderer/opengl/context.h" -#include "renderer/opengl/lookup.h" #include "renderer/render_factory.h" #include "renderer/render_pass.h" #include "renderer/render_target.h" @@ -167,10 +165,19 @@ void Presenter::init_graphics(const renderer::window_settings &window_settings) this->asset_manager, this->time_loop->get_clock()); this->render_passes.push_back(this->hud_renderer->get_render_pass()); + + for (auto& render_pass : render_passes) { + render_pass->set_stencil_state(renderer::StencilState::USE_STENCIL_TEST); + } this->init_gui(); this->init_final_render_pass(); + // set passes indices + this->index_gui_stencil_pass = this->render_passes.size() - 3; + this->index_gui_render_pass = this->render_passes.size() - 2; + this->index_final_render_pass = this->render_passes.size() - 1; + if (this->simulation) { auto render_factory = std::make_shared(this->terrain_renderer, this->world_renderer); this->simulation->attach_renderer(render_factory); @@ -213,7 +220,10 @@ void Presenter::init_gui() { qml_root, // directory to watch for qml file changes qml_assets, // qml data: Engine *, the data directory, ... this->renderer // openage renderer - ); + ); + + auto stencil_pass = this->gui->get_stencil_pass(); + this->render_passes.push_back(stencil_pass); auto gui_pass = this->gui->get_render_pass(); this->render_passes.push_back(gui_pass); @@ -309,31 +319,6 @@ void Presenter::init_final_render_pass() { }); } -void Presenter::init_stencil_test() { - glEnable(GL_STENCIL_TEST); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glClear(GL_STENCIL_BUFFER_BIT); -} - -void Presenter::enable_stencil_for_gui_mask() { - // Replace stencil value with 1 when depth test passes - glStencilFunc(GL_ALWAYS, 1, 0xFF); - glStencilMask(0xFF); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); -} - -void Presenter::enable_stencil_for_world() { - // Only pass if stencil value is not 1 - glStencilFunc(GL_NOTEQUAL, 1, 0xFF); - glStencilMask(0x00); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); -} - -void Presenter::disable_stencil() { - glDisable(GL_STENCIL_TEST); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); -} - void Presenter::render() { // TODO: Pass current time to update() instead of fetching it in renderer this->camera_manager->update(); @@ -341,25 +326,17 @@ void Presenter::render() { this->world_renderer->update(); this->hud_renderer->update(); - this->init_stencil_test(); - - // First Pass: Render GUI to stencil buffer - this->enable_stencil_for_gui_mask(); this->gui->render(); + this->renderer->render(this->render_passes[this->index_gui_stencil_pass]); - // Second Pass: Render game world with stencil buffer - this->enable_stencil_for_world(); - for (size_t i = 0; i < this->render_passes.size() - 2; ++i) { + for (size_t i = 0; i < this->index_gui_stencil_pass; ++i) { this->renderer->render(this->render_passes[i]); } - // Third Pass: Render GUI to screen - this->disable_stencil(); this->gui->render(); - this->renderer->render(this->render_passes[this->render_passes.size() - 2]); + this->renderer->render(this->render_passes[this->index_gui_render_pass]); - // Fourth Pass: Render screen to window - this->renderer->render(this->render_passes.back()); + this->renderer->render(this->render_passes[this->index_final_render_pass]); } } // namespace openage::presenter diff --git a/libopenage/presenter/presenter.h b/libopenage/presenter/presenter.h index 7bd4112929..d52f71009a 100644 --- a/libopenage/presenter/presenter.h +++ b/libopenage/presenter/presenter.h @@ -142,11 +142,6 @@ class Presenter { // void init_audio(); - void init_stencil_test(); - void enable_stencil_for_gui_mask(); - void enable_stencil_for_world(); - void disable_stencil(); - /** * Render all configured render passes in sequence. */ @@ -235,6 +230,13 @@ class Presenter { * Input manager. */ std::shared_ptr input_manager; + + /** + * Pass indices. + */ + size_t index_gui_stencil_pass; + size_t index_gui_render_pass; + size_t index_final_render_pass; }; } // namespace presenter diff --git a/libopenage/renderer/gui/gui.cpp b/libopenage/renderer/gui/gui.cpp index 879a709d0c..a881c7c6d4 100644 --- a/libopenage/renderer/gui/gui.cpp +++ b/libopenage/renderer/gui/gui.cpp @@ -62,6 +62,10 @@ std::shared_ptr GUI::get_render_pass() const { return this->render_pass; } +std::shared_ptr GUI::get_stencil_pass() const { + return this->stencil_pass; +} + void GUI::initialize_render_pass(size_t width, size_t height, const util::Path &shaderdir) { @@ -98,6 +102,10 @@ void GUI::initialize_render_pass(size_t width, // TODO: Rendering into the FBO is a bit redundant right now because we // just copy the GUI texture into the output texture this->render_pass = renderer->add_render_pass({display_obj}, fbo); + + auto stencil_pass = renderer->add_render_pass({display_obj}, fbo); + stencil_pass->set_stencil_state(StencilState::WRITE_STENCIL_MASK); + this->stencil_pass = stencil_pass; } diff --git a/libopenage/renderer/gui/gui.h b/libopenage/renderer/gui/gui.h index 7baa7306d4..59393f0d90 100644 --- a/libopenage/renderer/gui/gui.h +++ b/libopenage/renderer/gui/gui.h @@ -63,6 +63,13 @@ class GUI { */ std::shared_ptr get_render_pass() const; + /** + * Get the stencil render pass of the GUI. + * + * @return stencil render pass of the GUI + */ + std::shared_ptr get_stencil_pass() const; + /** * Render the GUI texture. */ @@ -139,6 +146,11 @@ class GUI { * this pass via a \p renderer::resources::Renderable. */ std::shared_ptr render_pass; + + /** + * Render pass for the stencil mask of the GUI. + */ + std::shared_ptr stencil_pass; }; } // namespace gui diff --git a/libopenage/renderer/opengl/renderer.cpp b/libopenage/renderer/opengl/renderer.cpp index 6d8d909a5b..a1e78f3823 100644 --- a/libopenage/renderer/opengl/renderer.cpp +++ b/libopenage/renderer/opengl/renderer.cpp @@ -162,6 +162,30 @@ void GlRenderer::optimize(const std::shared_ptr &pass) { } } +void GlRenderer::setupStencilWrite() { + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 1, 0xFF); + glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); + glStencilMask(0xFF); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + glDepthMask(GL_FALSE); +} + +void GlRenderer::setupStencilTest() { + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_NOTEQUAL, 1, 0xFF); + glStencilMask(0x00); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_TRUE); +} + +void GlRenderer::disableStencilTest() { + glDisable(GL_STENCIL_TEST); + glStencilMask(0xFF); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glDepthMask(GL_TRUE); +} + void GlRenderer::check_error() { // thanks for the global state, opengl! GlContext::check_error(); @@ -176,7 +200,12 @@ void GlRenderer::render(const std::shared_ptr &pass) { // see https://www.khronos.org/opengl/wiki/Vertex_Rendering#Causes_of_rendering_failure shared_quad_vao->bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + // ensure that an (empty) VAO is bound before rendering geometry + // a bound VAO is required to render bufferless quad geometries by OpenGL + // see https://www.khronos.org/opengl/wiki/Vertex_Rendering#Causes_of_rendering_failure + shared_quad_vao->bind(); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // TODO: Option for face culling // glEnable(GL_CULL_FACE); @@ -198,6 +227,20 @@ void GlRenderer::render(const std::shared_ptr &pass) { glClear(GL_DEPTH_BUFFER_BIT); } + switch (layer.stencil_state) { + case StencilState::WRITE_STENCIL_MASK: + setupStencilWrite(); + break; + + case StencilState::USE_STENCIL_TEST: + setupStencilTest(); + break; + + case StencilState::DISABLE_STENCIL: + disableStencilTest(); + break; + } + for (auto const &obj : objects) { if (obj.alpha_blending) { glEnable(GL_BLEND); diff --git a/libopenage/renderer/opengl/renderer.h b/libopenage/renderer/opengl/renderer.h index 751af7cacc..0a63634f47 100644 --- a/libopenage/renderer/opengl/renderer.h +++ b/libopenage/renderer/opengl/renderer.h @@ -63,6 +63,12 @@ class GlRenderer final : public Renderer { /// Optimize the render pass by reordering stuff static void optimize(const std::shared_ptr &pass); + void setupStencilWrite(); + + void setupStencilTest(); + + void disableStencilTest(); + /// The GL context. std::shared_ptr gl_context; diff --git a/libopenage/renderer/render_pass.cpp b/libopenage/renderer/render_pass.cpp index c925fc0a89..2747797e05 100644 --- a/libopenage/renderer/render_pass.cpp +++ b/libopenage/renderer/render_pass.cpp @@ -83,7 +83,7 @@ void RenderPass::add_renderables(Renderable &&renderable, int64_t priority) { this->add_renderables(std::vector{std::move(renderable)}, priority); } -void RenderPass::add_layer(int64_t priority, bool clear_depth) { +void RenderPass::add_layer(int64_t priority, bool clear_depth, StencilState stencil_state) { size_t layer_index = 0; for (const auto &layer : this->layers) { if (layer.priority > priority) { @@ -92,14 +92,20 @@ void RenderPass::add_layer(int64_t priority, bool clear_depth) { layer_index++; } - this->add_layer(layer_index, priority, clear_depth); + this->add_layer(layer_index, priority, clear_depth, stencil_state); } -void RenderPass::add_layer(size_t index, int64_t priority, bool clear_depth) { - this->layers.insert(this->layers.begin() + index, Layer{priority, clear_depth}); +void RenderPass::add_layer(size_t index, int64_t priority, bool clear_depth, StencilState stencil_state) { + this->layers.insert(this->layers.begin() + index, Layer{priority, clear_depth, stencil_state}); this->renderables.insert(this->renderables.begin() + index, std::vector{}); } +void RenderPass::set_stencil_state(StencilState state) { + for (auto &layer : this->layers) { + layer.stencil_state = state; + } +} + void RenderPass::clear_renderables() { // Keep layer definitions, but reset the length of each layer to 0 for (size_t i = 0; i < this->layers.size(); i++) { diff --git a/libopenage/renderer/render_pass.h b/libopenage/renderer/render_pass.h index 43c99bd659..3d7ddfe909 100644 --- a/libopenage/renderer/render_pass.h +++ b/libopenage/renderer/render_pass.h @@ -14,6 +14,18 @@ namespace openage { namespace renderer { class RenderTarget; +/** + * Stencil states for the render pass. + */ +enum class StencilState { + /// State for writing GUI elements to stencil buffer. + WRITE_STENCIL_MASK, + /// State for using the mask when rendering scene. + USE_STENCIL_TEST, + /// State for normal rendering (GUI rendering). + DISABLE_STENCIL, +}; + /** * Defines a layer in the render pass. A layer is a slice of the renderables * that have the same priority. Each layer can have its own settings. @@ -27,6 +39,8 @@ struct Layer { int64_t priority; /// Whether to clear the depth buffer before rendering this layer. bool clear_depth = true; + /// The state of the stencil buffer for the render pass. + StencilState stencil_state; }; /** @@ -95,8 +109,17 @@ class RenderPass { * * @param priority Priority of the layer. Layers with higher priority are drawn first. * @param clear_depth If true clears the depth buffer before rendering this layer. + * @param stencil_state State of the stencil buffer, using to do stencil test. */ - void add_layer(int64_t priority, bool clear_depth = true); + void add_layer(int64_t priority, bool clear_depth = true, + StencilState stencil_state = StencilState::DISABLE_STENCIL); + + /** + * Set the stencil state for the render pass. + * + * @param state The new stencil state. + */ + void set_stencil_state(StencilState state); /** * Clear the list of renderables @@ -137,9 +160,11 @@ class RenderPass { * * @param index Index in \p layers member to insert the new layer. * @param priority Priority of the layer. Layers with higher priority are drawn first. - * @param clear_depth If true clears the depth buffer before rendering this layer. + * @param clear_depth If true clears the depth buffer before rendering this layer. + * @param stencil_state State of the stencil buffer, using to do stencil test. */ - void add_layer(size_t index, int64_t priority, bool clear_depth = true); + void add_layer(size_t index, int64_t priority, bool clear_depth = true, + StencilState stencil_state = StencilState::DISABLE_STENCIL); /** * Render target to write to. From 7eca3b5fd7597d4a3d5cd5fef2ee27f7fed92893 Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Sun, 19 Jan 2025 14:17:07 -0500 Subject: [PATCH 04/14] clean some format issues --- libopenage/presenter/presenter.cpp | 6 +++--- libopenage/presenter/presenter.h | 2 +- libopenage/renderer/gui/gui.cpp | 2 +- libopenage/renderer/gui/gui.h | 6 +++--- libopenage/renderer/opengl/renderer.h | 4 ++-- libopenage/renderer/render_pass.cpp | 2 +- libopenage/renderer/render_pass.h | 20 +++++++++----------- 7 files changed, 20 insertions(+), 22 deletions(-) diff --git a/libopenage/presenter/presenter.cpp b/libopenage/presenter/presenter.cpp index c1ac699f68..608294025b 100644 --- a/libopenage/presenter/presenter.cpp +++ b/libopenage/presenter/presenter.cpp @@ -165,8 +165,8 @@ void Presenter::init_graphics(const renderer::window_settings &window_settings) this->asset_manager, this->time_loop->get_clock()); this->render_passes.push_back(this->hud_renderer->get_render_pass()); - - for (auto& render_pass : render_passes) { + + for (auto &render_pass : render_passes) { render_pass->set_stencil_state(renderer::StencilState::USE_STENCIL_TEST); } @@ -220,7 +220,7 @@ void Presenter::init_gui() { qml_root, // directory to watch for qml file changes qml_assets, // qml data: Engine *, the data directory, ... this->renderer // openage renderer - ); + ); auto stencil_pass = this->gui->get_stencil_pass(); this->render_passes.push_back(stencil_pass); diff --git a/libopenage/presenter/presenter.h b/libopenage/presenter/presenter.h index d52f71009a..65581b37ee 100644 --- a/libopenage/presenter/presenter.h +++ b/libopenage/presenter/presenter.h @@ -230,7 +230,7 @@ class Presenter { * Input manager. */ std::shared_ptr input_manager; - + /** * Pass indices. */ diff --git a/libopenage/renderer/gui/gui.cpp b/libopenage/renderer/gui/gui.cpp index a881c7c6d4..70ddb8ddb1 100644 --- a/libopenage/renderer/gui/gui.cpp +++ b/libopenage/renderer/gui/gui.cpp @@ -1,4 +1,4 @@ -// Copyright 2015-2024 the openage authors. See copying.md for legal info. +// Copyright 2015-2025 the openage authors. See copying.md for legal info. #include "gui.h" diff --git a/libopenage/renderer/gui/gui.h b/libopenage/renderer/gui/gui.h index 59393f0d90..fe9e351f2b 100644 --- a/libopenage/renderer/gui/gui.h +++ b/libopenage/renderer/gui/gui.h @@ -1,4 +1,4 @@ -// Copyright 2015-2024 the openage authors. See copying.md for legal info. +// Copyright 2015-2025 the openage authors. See copying.md for legal info. #pragma once @@ -65,8 +65,8 @@ class GUI { /** * Get the stencil render pass of the GUI. - * - * @return stencil render pass of the GUI + * + * @return stencil render pass of the GUI. */ std::shared_ptr get_stencil_pass() const; diff --git a/libopenage/renderer/opengl/renderer.h b/libopenage/renderer/opengl/renderer.h index 0a63634f47..2ac668ab0f 100644 --- a/libopenage/renderer/opengl/renderer.h +++ b/libopenage/renderer/opengl/renderer.h @@ -64,9 +64,9 @@ class GlRenderer final : public Renderer { static void optimize(const std::shared_ptr &pass); void setupStencilWrite(); - + void setupStencilTest(); - + void disableStencilTest(); /// The GL context. diff --git a/libopenage/renderer/render_pass.cpp b/libopenage/renderer/render_pass.cpp index 2747797e05..c9cd4e9e4b 100644 --- a/libopenage/renderer/render_pass.cpp +++ b/libopenage/renderer/render_pass.cpp @@ -1,4 +1,4 @@ -// Copyright 2024-2024 the openage authors. See copying.md for legal info. +// Copyright 2024-2025 the openage authors. See copying.md for legal info. #include "render_pass.h" diff --git a/libopenage/renderer/render_pass.h b/libopenage/renderer/render_pass.h index 3d7ddfe909..e0530d4167 100644 --- a/libopenage/renderer/render_pass.h +++ b/libopenage/renderer/render_pass.h @@ -1,4 +1,4 @@ -// Copyright 2024-2024 the openage authors. See copying.md for legal info. +// Copyright 2024-2025 the openage authors. See copying.md for legal info. #pragma once @@ -19,11 +19,11 @@ class RenderTarget; */ enum class StencilState { /// State for writing GUI elements to stencil buffer. - WRITE_STENCIL_MASK, + WRITE_STENCIL_MASK, /// State for using the mask when rendering scene. - USE_STENCIL_TEST, + USE_STENCIL_TEST, /// State for normal rendering (GUI rendering). - DISABLE_STENCIL, + DISABLE_STENCIL }; /** @@ -109,10 +109,9 @@ class RenderPass { * * @param priority Priority of the layer. Layers with higher priority are drawn first. * @param clear_depth If true clears the depth buffer before rendering this layer. - * @param stencil_state State of the stencil buffer, using to do stencil test. + * @param stencil_state State of the stencil buffer, using to do stencil test. */ - void add_layer(int64_t priority, bool clear_depth = true, - StencilState stencil_state = StencilState::DISABLE_STENCIL); + void add_layer(int64_t priority, bool clear_depth = true, StencilState stencil_state = StencilState::DISABLE_STENCIL); /** * Set the stencil state for the render pass. @@ -160,11 +159,10 @@ class RenderPass { * * @param index Index in \p layers member to insert the new layer. * @param priority Priority of the layer. Layers with higher priority are drawn first. - * @param clear_depth If true clears the depth buffer before rendering this layer. - * @param stencil_state State of the stencil buffer, using to do stencil test. + * @param clear_depth If true clears the depth buffer before rendering this layer. + * @param stencil_state State of the stencil buffer, using to do stencil test. */ - void add_layer(size_t index, int64_t priority, bool clear_depth = true, - StencilState stencil_state = StencilState::DISABLE_STENCIL); + void add_layer(size_t index, int64_t priority, bool clear_depth = true, StencilState stencil_state = StencilState::DISABLE_STENCIL); /** * Render target to write to. From b33abad5fdbd2e856bd662f86749c300186ba167 Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Thu, 30 Jan 2025 10:37:44 -0500 Subject: [PATCH 05/14] Revert files to pre-PR state --- libopenage/presenter/presenter.cpp | 25 ++------------ libopenage/presenter/presenter.h | 9 +---- libopenage/renderer/gui/gui.cpp | 10 +----- libopenage/renderer/gui/gui.h | 14 +------- libopenage/renderer/opengl/renderer.cpp | 45 +------------------------ libopenage/renderer/opengl/renderer.h | 6 ---- libopenage/renderer/render_pass.cpp | 16 +++------ libopenage/renderer/render_pass.h | 29 ++-------------- 8 files changed, 15 insertions(+), 139 deletions(-) diff --git a/libopenage/presenter/presenter.cpp b/libopenage/presenter/presenter.cpp index 608294025b..9775b62d9b 100644 --- a/libopenage/presenter/presenter.cpp +++ b/libopenage/presenter/presenter.cpp @@ -1,4 +1,4 @@ -// Copyright 2019-2025 the openage authors. See copying.md for legal info. +// Copyright 2019-2024 the openage authors. See copying.md for legal info. #include "presenter.h" @@ -166,18 +166,9 @@ void Presenter::init_graphics(const renderer::window_settings &window_settings) this->time_loop->get_clock()); this->render_passes.push_back(this->hud_renderer->get_render_pass()); - for (auto &render_pass : render_passes) { - render_pass->set_stencil_state(renderer::StencilState::USE_STENCIL_TEST); - } - this->init_gui(); this->init_final_render_pass(); - // set passes indices - this->index_gui_stencil_pass = this->render_passes.size() - 3; - this->index_gui_render_pass = this->render_passes.size() - 2; - this->index_final_render_pass = this->render_passes.size() - 1; - if (this->simulation) { auto render_factory = std::make_shared(this->terrain_renderer, this->world_renderer); this->simulation->attach_renderer(render_factory); @@ -222,9 +213,6 @@ void Presenter::init_gui() { this->renderer // openage renderer ); - auto stencil_pass = this->gui->get_stencil_pass(); - this->render_passes.push_back(stencil_pass); - auto gui_pass = this->gui->get_render_pass(); this->render_passes.push_back(gui_pass); } @@ -325,18 +313,11 @@ void Presenter::render() { this->terrain_renderer->update(); this->world_renderer->update(); this->hud_renderer->update(); - this->gui->render(); - this->renderer->render(this->render_passes[this->index_gui_stencil_pass]); - for (size_t i = 0; i < this->index_gui_stencil_pass; ++i) { - this->renderer->render(this->render_passes[i]); + for (auto &pass : this->render_passes) { + this->renderer->render(pass); } - - this->gui->render(); - this->renderer->render(this->render_passes[this->index_gui_render_pass]); - - this->renderer->render(this->render_passes[this->index_final_render_pass]); } } // namespace openage::presenter diff --git a/libopenage/presenter/presenter.h b/libopenage/presenter/presenter.h index 65581b37ee..2059daeed0 100644 --- a/libopenage/presenter/presenter.h +++ b/libopenage/presenter/presenter.h @@ -1,4 +1,4 @@ -// Copyright 2019-2025 the openage authors. See copying.md for legal info. +// Copyright 2019-2024 the openage authors. See copying.md for legal info. #pragma once @@ -230,13 +230,6 @@ class Presenter { * Input manager. */ std::shared_ptr input_manager; - - /** - * Pass indices. - */ - size_t index_gui_stencil_pass; - size_t index_gui_render_pass; - size_t index_final_render_pass; }; } // namespace presenter diff --git a/libopenage/renderer/gui/gui.cpp b/libopenage/renderer/gui/gui.cpp index 70ddb8ddb1..879a709d0c 100644 --- a/libopenage/renderer/gui/gui.cpp +++ b/libopenage/renderer/gui/gui.cpp @@ -1,4 +1,4 @@ -// Copyright 2015-2025 the openage authors. See copying.md for legal info. +// Copyright 2015-2024 the openage authors. See copying.md for legal info. #include "gui.h" @@ -62,10 +62,6 @@ std::shared_ptr GUI::get_render_pass() const { return this->render_pass; } -std::shared_ptr GUI::get_stencil_pass() const { - return this->stencil_pass; -} - void GUI::initialize_render_pass(size_t width, size_t height, const util::Path &shaderdir) { @@ -102,10 +98,6 @@ void GUI::initialize_render_pass(size_t width, // TODO: Rendering into the FBO is a bit redundant right now because we // just copy the GUI texture into the output texture this->render_pass = renderer->add_render_pass({display_obj}, fbo); - - auto stencil_pass = renderer->add_render_pass({display_obj}, fbo); - stencil_pass->set_stencil_state(StencilState::WRITE_STENCIL_MASK); - this->stencil_pass = stencil_pass; } diff --git a/libopenage/renderer/gui/gui.h b/libopenage/renderer/gui/gui.h index fe9e351f2b..7baa7306d4 100644 --- a/libopenage/renderer/gui/gui.h +++ b/libopenage/renderer/gui/gui.h @@ -1,4 +1,4 @@ -// Copyright 2015-2025 the openage authors. See copying.md for legal info. +// Copyright 2015-2024 the openage authors. See copying.md for legal info. #pragma once @@ -63,13 +63,6 @@ class GUI { */ std::shared_ptr get_render_pass() const; - /** - * Get the stencil render pass of the GUI. - * - * @return stencil render pass of the GUI. - */ - std::shared_ptr get_stencil_pass() const; - /** * Render the GUI texture. */ @@ -146,11 +139,6 @@ class GUI { * this pass via a \p renderer::resources::Renderable. */ std::shared_ptr render_pass; - - /** - * Render pass for the stencil mask of the GUI. - */ - std::shared_ptr stencil_pass; }; } // namespace gui diff --git a/libopenage/renderer/opengl/renderer.cpp b/libopenage/renderer/opengl/renderer.cpp index a1e78f3823..6d8d909a5b 100644 --- a/libopenage/renderer/opengl/renderer.cpp +++ b/libopenage/renderer/opengl/renderer.cpp @@ -162,30 +162,6 @@ void GlRenderer::optimize(const std::shared_ptr &pass) { } } -void GlRenderer::setupStencilWrite() { - glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_ALWAYS, 1, 0xFF); - glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); - glStencilMask(0xFF); - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - glDepthMask(GL_FALSE); -} - -void GlRenderer::setupStencilTest() { - glEnable(GL_STENCIL_TEST); - glStencilFunc(GL_NOTEQUAL, 1, 0xFF); - glStencilMask(0x00); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthMask(GL_TRUE); -} - -void GlRenderer::disableStencilTest() { - glDisable(GL_STENCIL_TEST); - glStencilMask(0xFF); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glDepthMask(GL_TRUE); -} - void GlRenderer::check_error() { // thanks for the global state, opengl! GlContext::check_error(); @@ -200,12 +176,7 @@ void GlRenderer::render(const std::shared_ptr &pass) { // see https://www.khronos.org/opengl/wiki/Vertex_Rendering#Causes_of_rendering_failure shared_quad_vao->bind(); - // ensure that an (empty) VAO is bound before rendering geometry - // a bound VAO is required to render bufferless quad geometries by OpenGL - // see https://www.khronos.org/opengl/wiki/Vertex_Rendering#Causes_of_rendering_failure - shared_quad_vao->bind(); - - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // TODO: Option for face culling // glEnable(GL_CULL_FACE); @@ -227,20 +198,6 @@ void GlRenderer::render(const std::shared_ptr &pass) { glClear(GL_DEPTH_BUFFER_BIT); } - switch (layer.stencil_state) { - case StencilState::WRITE_STENCIL_MASK: - setupStencilWrite(); - break; - - case StencilState::USE_STENCIL_TEST: - setupStencilTest(); - break; - - case StencilState::DISABLE_STENCIL: - disableStencilTest(); - break; - } - for (auto const &obj : objects) { if (obj.alpha_blending) { glEnable(GL_BLEND); diff --git a/libopenage/renderer/opengl/renderer.h b/libopenage/renderer/opengl/renderer.h index 2ac668ab0f..751af7cacc 100644 --- a/libopenage/renderer/opengl/renderer.h +++ b/libopenage/renderer/opengl/renderer.h @@ -63,12 +63,6 @@ class GlRenderer final : public Renderer { /// Optimize the render pass by reordering stuff static void optimize(const std::shared_ptr &pass); - void setupStencilWrite(); - - void setupStencilTest(); - - void disableStencilTest(); - /// The GL context. std::shared_ptr gl_context; diff --git a/libopenage/renderer/render_pass.cpp b/libopenage/renderer/render_pass.cpp index c9cd4e9e4b..c925fc0a89 100644 --- a/libopenage/renderer/render_pass.cpp +++ b/libopenage/renderer/render_pass.cpp @@ -1,4 +1,4 @@ -// Copyright 2024-2025 the openage authors. See copying.md for legal info. +// Copyright 2024-2024 the openage authors. See copying.md for legal info. #include "render_pass.h" @@ -83,7 +83,7 @@ void RenderPass::add_renderables(Renderable &&renderable, int64_t priority) { this->add_renderables(std::vector{std::move(renderable)}, priority); } -void RenderPass::add_layer(int64_t priority, bool clear_depth, StencilState stencil_state) { +void RenderPass::add_layer(int64_t priority, bool clear_depth) { size_t layer_index = 0; for (const auto &layer : this->layers) { if (layer.priority > priority) { @@ -92,20 +92,14 @@ void RenderPass::add_layer(int64_t priority, bool clear_depth, StencilState sten layer_index++; } - this->add_layer(layer_index, priority, clear_depth, stencil_state); + this->add_layer(layer_index, priority, clear_depth); } -void RenderPass::add_layer(size_t index, int64_t priority, bool clear_depth, StencilState stencil_state) { - this->layers.insert(this->layers.begin() + index, Layer{priority, clear_depth, stencil_state}); +void RenderPass::add_layer(size_t index, int64_t priority, bool clear_depth) { + this->layers.insert(this->layers.begin() + index, Layer{priority, clear_depth}); this->renderables.insert(this->renderables.begin() + index, std::vector{}); } -void RenderPass::set_stencil_state(StencilState state) { - for (auto &layer : this->layers) { - layer.stencil_state = state; - } -} - void RenderPass::clear_renderables() { // Keep layer definitions, but reset the length of each layer to 0 for (size_t i = 0; i < this->layers.size(); i++) { diff --git a/libopenage/renderer/render_pass.h b/libopenage/renderer/render_pass.h index e0530d4167..43c99bd659 100644 --- a/libopenage/renderer/render_pass.h +++ b/libopenage/renderer/render_pass.h @@ -1,4 +1,4 @@ -// Copyright 2024-2025 the openage authors. See copying.md for legal info. +// Copyright 2024-2024 the openage authors. See copying.md for legal info. #pragma once @@ -14,18 +14,6 @@ namespace openage { namespace renderer { class RenderTarget; -/** - * Stencil states for the render pass. - */ -enum class StencilState { - /// State for writing GUI elements to stencil buffer. - WRITE_STENCIL_MASK, - /// State for using the mask when rendering scene. - USE_STENCIL_TEST, - /// State for normal rendering (GUI rendering). - DISABLE_STENCIL -}; - /** * Defines a layer in the render pass. A layer is a slice of the renderables * that have the same priority. Each layer can have its own settings. @@ -39,8 +27,6 @@ struct Layer { int64_t priority; /// Whether to clear the depth buffer before rendering this layer. bool clear_depth = true; - /// The state of the stencil buffer for the render pass. - StencilState stencil_state; }; /** @@ -109,16 +95,8 @@ class RenderPass { * * @param priority Priority of the layer. Layers with higher priority are drawn first. * @param clear_depth If true clears the depth buffer before rendering this layer. - * @param stencil_state State of the stencil buffer, using to do stencil test. - */ - void add_layer(int64_t priority, bool clear_depth = true, StencilState stencil_state = StencilState::DISABLE_STENCIL); - - /** - * Set the stencil state for the render pass. - * - * @param state The new stencil state. */ - void set_stencil_state(StencilState state); + void add_layer(int64_t priority, bool clear_depth = true); /** * Clear the list of renderables @@ -160,9 +138,8 @@ class RenderPass { * @param index Index in \p layers member to insert the new layer. * @param priority Priority of the layer. Layers with higher priority are drawn first. * @param clear_depth If true clears the depth buffer before rendering this layer. - * @param stencil_state State of the stencil buffer, using to do stencil test. */ - void add_layer(size_t index, int64_t priority, bool clear_depth = true, StencilState stencil_state = StencilState::DISABLE_STENCIL); + void add_layer(size_t index, int64_t priority, bool clear_depth = true); /** * Render target to write to. From eb3d4a7771dd65a8e7c379b2fc07794264f66983 Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Thu, 30 Jan 2025 15:17:47 -0500 Subject: [PATCH 06/14] add stencil_depth attachment into framebuffer --- libopenage/renderer/opengl/framebuffer.cpp | 5 ++++- libopenage/renderer/opengl/lookup.h | 5 +++-- libopenage/renderer/resources/texture_info.h | 7 +++++-- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/libopenage/renderer/opengl/framebuffer.cpp b/libopenage/renderer/opengl/framebuffer.cpp index 0ad46c1563..6cffcf877f 100644 --- a/libopenage/renderer/opengl/framebuffer.cpp +++ b/libopenage/renderer/opengl/framebuffer.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2024 the openage authors. See copying.md for legal info. +// Copyright 2017-2025 the openage authors. See copying.md for legal info. #include "framebuffer.h" @@ -42,6 +42,9 @@ GlFramebuffer::GlFramebuffer(const std::shared_ptr &context, if (texture->get_info().get_format() == resources::pixel_format::depth24) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture->get_handle(), 0); } + else if (texture->get_info().get_format() == resources::pixel_format::depth24_stencil8) { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture->get_handle(), 0); + } else { auto attachmentPoint = GL_COLOR_ATTACHMENT0 + colorTextureCount++; glFramebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, texture->get_handle(), 0); diff --git a/libopenage/renderer/opengl/lookup.h b/libopenage/renderer/opengl/lookup.h index 9521369ef5..54d8e108eb 100644 --- a/libopenage/renderer/opengl/lookup.h +++ b/libopenage/renderer/opengl/lookup.h @@ -1,4 +1,4 @@ -// Copyright 2018-2024 the openage authors. See copying.md for legal info. +// Copyright 2018-2025 the openage authors. See copying.md for legal info. // Lookup tables for translating between OpenGL-specific values and generic renderer values, // as well as mapping things like type sizes within OpenGL. @@ -25,7 +25,8 @@ static constexpr auto GL_PIXEL_FORMAT = datastructure::create_const_map( diff --git a/libopenage/renderer/resources/texture_info.h b/libopenage/renderer/resources/texture_info.h index 7884fe0f79..8cc4681287 100644 --- a/libopenage/renderer/resources/texture_info.h +++ b/libopenage/renderer/resources/texture_info.h @@ -1,4 +1,4 @@ -// Copyright 2017-2024 the openage authors. See copying.md for legal info. +// Copyright 2017-2025 the openage authors. See copying.md for legal info. #pragma once @@ -30,6 +30,8 @@ enum class pixel_format { bgr8, /// 24 bits per pixel, depth texture depth24, + /// 32 bits per pixel, depth texture + stencil + depth24_stencil8, /// 32 bits per pixel, float, alpha channel, RGBA order rgba8, /// 32 bits per pixel, unsigned integer, alpha channel, RGBA order @@ -51,7 +53,8 @@ constexpr size_t pixel_size(pixel_format fmt) { std::make_pair(pixel_format::bgr8, 3), std::make_pair(pixel_format::rgba8, 4), std::make_pair(pixel_format::rgba8ui, 4), - std::make_pair(pixel_format::depth24, 3)); + std::make_pair(pixel_format::depth24, 3), + std::make_pair(pixel_format::depth24_stencil8, 4)); return pix_size.get(fmt); } From bc8584fb6fe1fb0430d09d5ee0166ef401c2fd4e Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Thu, 30 Jan 2025 15:52:21 -0500 Subject: [PATCH 07/14] implement stencil test in render pass and renderer --- libopenage/renderer/gui/gui.cpp | 14 ++++++++++--- libopenage/renderer/opengl/render_pass.cpp | 16 ++++++++++++++- libopenage/renderer/opengl/render_pass.h | 23 +++++++++++++++++++++- libopenage/renderer/opengl/renderer.cpp | 10 ++++++++++ 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/libopenage/renderer/gui/gui.cpp b/libopenage/renderer/gui/gui.cpp index 879a709d0c..e6ff00ac60 100644 --- a/libopenage/renderer/gui/gui.cpp +++ b/libopenage/renderer/gui/gui.cpp @@ -1,4 +1,4 @@ -// Copyright 2015-2024 the openage authors. See copying.md for legal info. +// Copyright 2015-2025 the openage authors. See copying.md for legal info. #include "gui.h" @@ -7,6 +7,7 @@ #include "renderer/gui/guisys/public/gui_renderer.h" #include "renderer/gui/integration/public/gui_application_with_logger.h" #include "renderer/opengl/context.h" +#include "renderer/opengl/render_pass.h" #include "renderer/render_pass.h" #include "renderer/render_target.h" #include "renderer/renderer.h" @@ -85,19 +86,26 @@ void GUI::initialize_render_pass(size_t width, // GUI draw surface. gets drawn on top of the gameworld in the presenter. auto output_texture = this->renderer->add_texture( resources::Texture2dInfo(width, height, resources::pixel_format::rgba8)); - auto fbo = this->renderer->create_texture_target({output_texture}); + auto depth_stencil_texture = this->renderer->add_texture( + resources::Texture2dInfo(width, height, resources::pixel_format::depth24_stencil8)); + auto fbo = this->renderer->create_texture_target({output_texture, depth_stencil_texture}); this->texture_unif = maptex_shader->new_uniform_input("texture", this->texture); Renderable display_obj{ this->texture_unif, quad, true, - true, + false, }; // TODO: Rendering into the FBO is a bit redundant right now because we // just copy the GUI texture into the output texture this->render_pass = renderer->add_render_pass({display_obj}, fbo); + + auto gl_pass = std::dynamic_pointer_cast(this->render_pass); + if (gl_pass) { + gl_pass->set_stencil_config(true, true, 1, 0xFF, 0xFF, GL_ALWAYS); + } } diff --git a/libopenage/renderer/opengl/render_pass.cpp b/libopenage/renderer/opengl/render_pass.cpp index 6d2ab052c1..e043d4a1f8 100644 --- a/libopenage/renderer/opengl/render_pass.cpp +++ b/libopenage/renderer/opengl/render_pass.cpp @@ -1,4 +1,4 @@ -// Copyright 2019-2024 the openage authors. See copying.md for legal info. +// Copyright 2019-2025 the openage authors. See copying.md for legal info. #include "render_pass.h" @@ -35,4 +35,18 @@ bool GlRenderPass::get_is_optimized() const { void GlRenderPass::set_is_optimized(bool flag) { this->is_optimized = flag; } + +void GlRenderPass::set_stencil_config(bool enabled, bool write, uint8_t ref_value, uint8_t write_mask, uint8_t read_mask, GLenum test_func) { + this->stencil_config.enabled = enabled; + this->stencil_config.write = write; + this->stencil_config.ref_value = ref_value; + this->stencil_config.write_mask = write_mask; + this->stencil_config.read_mask = read_mask; + this->stencil_config.test_func = test_func; +} + +const StencilConfig &GlRenderPass::get_stencil_config() const { + return this->stencil_config; +} + } // namespace openage::renderer::opengl diff --git a/libopenage/renderer/opengl/render_pass.h b/libopenage/renderer/opengl/render_pass.h index 87ea8448c9..0a779d673f 100644 --- a/libopenage/renderer/opengl/render_pass.h +++ b/libopenage/renderer/opengl/render_pass.h @@ -1,13 +1,28 @@ -// Copyright 2019-2024 the openage authors. See copying.md for legal info. +// Copyright 2019-2025 the openage authors. See copying.md for legal info. #pragma once +#include "renderer/opengl/lookup.h" #include "renderer/render_pass.h" #include "renderer/renderable.h" namespace openage::renderer::opengl { +struct StencilConfig { + bool enabled = false; + /// Whether to write to stencil buffer + bool write = false; + /// Reference value for stencil test + uint8_t ref_value = 1; + /// Mask for writing to stencil buffer + uint8_t write_mask = 0xFF; + /// Mask for reading from stencil buffer + uint8_t read_mask = 0xFF; + /// Stencil test function + GLenum test_func = GL_EQUAL; +}; + class GlRenderPass final : public RenderPass { public: GlRenderPass(std::vector &&renderables, @@ -20,9 +35,15 @@ class GlRenderPass final : public RenderPass { void set_is_optimized(bool); bool get_is_optimized() const; + void set_stencil_config(bool enabled, bool write, uint8_t ref_value = 1, uint8_t write_mask = 0xFF, uint8_t read_mask = 0xFF, GLenum test_func = GL_EQUAL); + const StencilConfig &get_stencil_config() const; + private: /// Whether the renderables order is optimised bool is_optimized; + + /// The currentstencil configuration. + StencilConfig stencil_config; }; } // namespace openage::renderer::opengl diff --git a/libopenage/renderer/opengl/renderer.cpp b/libopenage/renderer/opengl/renderer.cpp index 6d8d909a5b..954c28caf9 100644 --- a/libopenage/renderer/opengl/renderer.cpp +++ b/libopenage/renderer/opengl/renderer.cpp @@ -188,12 +188,22 @@ void GlRenderer::render(const std::shared_ptr &pass) { // render all objects in the pass const auto &layers = gl_pass->get_layers(); const auto &renderables = gl_pass->get_renderables(); + const auto &stencil_config = gl_pass->get_stencil_config(); // Draw by layers for (size_t i = 0; i < layers.size(); i++) { const auto &layer = layers[i]; const auto &objects = renderables[i]; + if (stencil_config.enabled) { + glEnable(GL_STENCIL_TEST); + glStencilMask(stencil_config.write ? stencil_config.write_mask : 0x00); + glStencilFunc(stencil_config.test_func, stencil_config.ref_value, stencil_config.read_mask); + } + else { + glDisable(GL_STENCIL_TEST); + } + if (layer.clear_depth) { glClear(GL_DEPTH_BUFFER_BIT); } From f1c27288217b68edd40cc6e95690e215e34c4970 Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Sun, 2 Feb 2025 15:14:34 -0500 Subject: [PATCH 08/14] add stencil test demo --- .../test/shaders/demo_8_gui_stencil.frag.glsl | 20 +++ .../test/shaders/demo_8_gui_stencil.vert.glsl | 11 ++ .../test/shaders/demo_8_simple_gui.frag.glsl | 17 +++ .../test/shaders/demo_8_simple_gui.vert.glsl | 15 ++ libopenage/renderer/demo/CMakeLists.txt | 1 + libopenage/renderer/demo/demo_8.cpp | 143 ++++++++++++++++++ libopenage/renderer/demo/demo_8.h | 18 +++ libopenage/renderer/demo/tests.cpp | 5 + 8 files changed, 230 insertions(+) create mode 100644 assets/test/shaders/demo_8_gui_stencil.frag.glsl create mode 100644 assets/test/shaders/demo_8_gui_stencil.vert.glsl create mode 100644 assets/test/shaders/demo_8_simple_gui.frag.glsl create mode 100644 assets/test/shaders/demo_8_simple_gui.vert.glsl create mode 100644 libopenage/renderer/demo/demo_8.cpp create mode 100644 libopenage/renderer/demo/demo_8.h diff --git a/assets/test/shaders/demo_8_gui_stencil.frag.glsl b/assets/test/shaders/demo_8_gui_stencil.frag.glsl new file mode 100644 index 0000000000..721ccf2ab9 --- /dev/null +++ b/assets/test/shaders/demo_8_gui_stencil.frag.glsl @@ -0,0 +1,20 @@ +#version 330 + +in vec2 v_uv; +uniform float time; // Add time uniform for animation + +out vec4 fragColor; + +void main() { + // Create moving gradient based on UV coordinates and time + vec2 moving_uv = v_uv + vec2(sin(time * 0.5) * 0.5, cos(time * 0.3) * 0.5); + + // Create some colorful pattern + vec3 color1 = vec3(0.2, 0.5, 0.8); // Blue-ish + vec3 color2 = vec3(0.8, 0.2, 0.5); // Pink-ish + + vec3 color = mix(color1, color2, sin(moving_uv.x * 5.0 + time) * 0.5 + 0.5); + color += vec3(0.2) * sin(moving_uv.y * 10.0 + time * 2.0); + + fragColor = vec4(color, 1.0); +} diff --git a/assets/test/shaders/demo_8_gui_stencil.vert.glsl b/assets/test/shaders/demo_8_gui_stencil.vert.glsl new file mode 100644 index 0000000000..b414147f3b --- /dev/null +++ b/assets/test/shaders/demo_8_gui_stencil.vert.glsl @@ -0,0 +1,11 @@ +#version 330 + +layout(location = 0) in vec2 position; +layout(location = 1) in vec2 uv; + +out vec2 v_uv; + +void main() { + gl_Position = vec4(position, 0.0, 1.0); + v_uv = uv; +} diff --git a/assets/test/shaders/demo_8_simple_gui.frag.glsl b/assets/test/shaders/demo_8_simple_gui.frag.glsl new file mode 100644 index 0000000000..16634353b5 --- /dev/null +++ b/assets/test/shaders/demo_8_simple_gui.frag.glsl @@ -0,0 +1,17 @@ +#version 330 + +in vec2 v_uv; +out vec4 fragColor; + +void main() { + // Semi-transparent white color for the GUI + vec4 gui_color = vec4(1.0, 1.0, 1.0, 0.7); + + // Add a border to make it look more like a GUI window + float border = 0.05; + if (v_uv.x < border || v_uv.x > 1.0 - border || v_uv.y < border || v_uv.y > 1.0 - border) { + gui_color = vec4(0.8, 0.8, 0.8, 0.9); // Darker border + } + + fragColor = gui_color; +} \ No newline at end of file diff --git a/assets/test/shaders/demo_8_simple_gui.vert.glsl b/assets/test/shaders/demo_8_simple_gui.vert.glsl new file mode 100644 index 0000000000..59d0b224bb --- /dev/null +++ b/assets/test/shaders/demo_8_simple_gui.vert.glsl @@ -0,0 +1,15 @@ +#version 330 + +layout(location = 0) in vec2 position; +layout(location = 1) in vec2 uv; + +out vec2 v_uv; + +void main() { + // Scale down the quad to show part of the background + vec2 scaled_pos = position * 0.5; // Make it half size + // Move it to top-right corner + scaled_pos += vec2(0.5, 0.5); + gl_Position = vec4(scaled_pos, 0.0, 1.0); + v_uv = uv; +} diff --git a/libopenage/renderer/demo/CMakeLists.txt b/libopenage/renderer/demo/CMakeLists.txt index fb93e5279b..1c5f732633 100644 --- a/libopenage/renderer/demo/CMakeLists.txt +++ b/libopenage/renderer/demo/CMakeLists.txt @@ -6,6 +6,7 @@ add_sources(libopenage demo_4.cpp demo_5.cpp demo_6.cpp + demo_8.cpp stresstest_0.cpp stresstest_1.cpp tests.cpp diff --git a/libopenage/renderer/demo/demo_8.cpp b/libopenage/renderer/demo/demo_8.cpp new file mode 100644 index 0000000000..f0d01d9492 --- /dev/null +++ b/libopenage/renderer/demo/demo_8.cpp @@ -0,0 +1,143 @@ +// Copyright 2023-2025 the openage authors. See copying.md for legal info. + +#include "demo_8.h" + +#include "renderer/demo/util.h" +#include "renderer/gui/gui.h" +#include "renderer/gui/integration/public/gui_application_with_logger.h" +#include "renderer/opengl/render_pass.h" +#include "renderer/opengl/renderer.h" +#include "renderer/opengl/window.h" +#include "renderer/render_pass.h" +#include "renderer/render_target.h" +#include "renderer/resources/mesh_data.h" +#include "renderer/resources/shader_source.h" +#include "renderer/shader_program.h" + + +namespace openage::renderer::tests { + +void renderer_demo_8(const util::Path &path) { + auto qtapp = std::make_shared(); + + // Create window and renderer + window_settings settings; + settings.width = 800; + settings.height = 600; + settings.debug = true; + auto window = std::make_shared("openage renderer stencil test", settings); + auto renderer = window->make_renderer(); + + auto shaderdir = path / "assets" / "test" / "shaders"; + + // Create background shader (something that would be masked by GUI) + auto bg_vshader_file = (shaderdir / "demo_8_gui_stencil.vert.glsl").open(); + auto bg_vshader_src = resources::ShaderSource( + resources::shader_lang_t::glsl, + resources::shader_stage_t::vertex, + bg_vshader_file.read()); + bg_vshader_file.close(); + + auto bg_fshader_file = (shaderdir / "demo_8_gui_stencil.frag.glsl").open(); + auto bg_fshader_src = resources::ShaderSource( + resources::shader_lang_t::glsl, + resources::shader_stage_t::fragment, + bg_fshader_file.read()); + bg_fshader_file.close(); + + // Load simple GUI quad shader from + auto gui_vshader_file = (shaderdir / "demo_8_simple_gui.vert.glsl").open(); + auto gui_vshader_src = resources::ShaderSource( + resources::shader_lang_t::glsl, + resources::shader_stage_t::vertex, + gui_vshader_file.read()); + gui_vshader_file.close(); + + auto gui_fshader_file = (shaderdir / "demo_8_simple_gui.frag.glsl").open(); + auto gui_fshader_src = resources::ShaderSource( + resources::shader_lang_t::glsl, + resources::shader_stage_t::fragment, + gui_fshader_file.read()); + gui_fshader_file.close(); + + auto bg_shader = renderer->add_shader({bg_vshader_src, bg_fshader_src}); + auto gui_shader = renderer->add_shader({gui_vshader_src, gui_fshader_src}); + + auto quad = renderer->add_mesh_geometry(resources::MeshData::make_quad()); + + auto bg_uniforms = bg_shader->new_uniform_input(); + auto gui_uniforms = gui_shader->new_uniform_input(); + + Renderable bg_obj{ + bg_uniforms, + quad, + false, + true, // Enable depth test + }; + + Renderable gui_obj{ + gui_uniforms, + quad, + true, // Enable alpha blending + false, // No depth test needed + }; + + auto depth_stencil_texture = renderer->add_texture( + resources::Texture2dInfo( + settings.width, settings.height, resources::pixel_format::depth24_stencil8)); + auto stencil_fbo = renderer->create_texture_target({depth_stencil_texture}); + + //auto bg_pass = renderer->add_render_pass({bg_obj}, renderer->get_display_target()); + auto bg_pass = renderer->add_render_pass({bg_obj}, renderer->get_display_target()); + auto gui_pass = renderer->add_render_pass({gui_obj}, renderer->get_display_target()); + auto gui_stencil_pass = renderer->add_render_pass({gui_obj}, stencil_fbo); + + // Configure stencil testing for background pass + auto gl_bg_pass = std::dynamic_pointer_cast(bg_pass); + if (gl_bg_pass) { + renderer::opengl::StencilConfig config; + config.enabled = true; + config.write = false; + config.ref_value = 1; + config.test_func = GL_NOTEQUAL; + config.depth_pass = GL_KEEP; + gl_bg_pass->set_stencil_config(config); + } + + auto gl_gui_stencil_pass = std::dynamic_pointer_cast(gui_stencil_pass); + if (gl_gui_stencil_pass) { + renderer::opengl::StencilConfig config; + config.enabled = true; + config.write = true; + config.ref_value = 1; + config.test_func = GL_ALWAYS; + config.depth_pass = GL_REPLACE; + gl_gui_stencil_pass->set_stencil_config(config); + } + + log::log(INFO << "Stencil Test Demo Instructions:"); + log::log(INFO << " 1. GUI elements will create a stencil mask"); + log::log(INFO << " 2. Background will only render in non-GUI areas"); + + float current_time = 0.0f; + + while (not window->should_close()) { + current_time += 0.01f; + bg_uniforms->update("time", current_time); + + // Render background and GUI + renderer->render(gui_stencil_pass); + + renderer->render(bg_pass); + + renderer->render(gui_pass); + + window->update(); + qtapp->process_events(); + + renderer->check_error(); + } + window->close(); +} + +} // namespace openage::renderer::tests \ No newline at end of file diff --git a/libopenage/renderer/demo/demo_8.h b/libopenage/renderer/demo/demo_8.h new file mode 100644 index 0000000000..d05570cf6f --- /dev/null +++ b/libopenage/renderer/demo/demo_8.h @@ -0,0 +1,18 @@ +// Copyright 2023-2025 the openage authors. See copying.md for legal info. + +#pragma once + +#include "util/path.h" + +namespace openage::renderer::tests { + +/** + * Show a demo of stencil testing. + * - GUI elements will create a stencil mask + * - Background will only render in non-GUI areas + * + * @param path Path to the project rootdir. + */ +void renderer_demo_8(const util::Path &path); + +} // namespace openage::renderer::tests diff --git a/libopenage/renderer/demo/tests.cpp b/libopenage/renderer/demo/tests.cpp index d3fb0e3c21..58c21e848d 100644 --- a/libopenage/renderer/demo/tests.cpp +++ b/libopenage/renderer/demo/tests.cpp @@ -12,6 +12,7 @@ #include "renderer/demo/demo_4.h" #include "renderer/demo/demo_5.h" #include "renderer/demo/demo_6.h" +#include "renderer/demo/demo_8.h" #include "renderer/demo/stresstest_0.h" #include "renderer/demo/stresstest_1.h" @@ -47,6 +48,10 @@ void renderer_demo(int demo_id, const util::Path &path) { renderer_demo_6(path); break; + case 8: + renderer_demo_8(path); + break; + default: log::log(MSG(err) << "Unknown renderer demo requested: " << demo_id << "."); break; From 6043b1e97e31839d700a1f5a6f7ffe43b2b0ad2b Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Sun, 2 Feb 2025 15:15:30 -0500 Subject: [PATCH 09/14] update stencil config in renderpass and gui --- libopenage/renderer/gui/gui.cpp | 9 +++++++-- libopenage/renderer/opengl/render_pass.cpp | 9 ++------- libopenage/renderer/opengl/render_pass.h | 12 +++++++++--- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/libopenage/renderer/gui/gui.cpp b/libopenage/renderer/gui/gui.cpp index e6ff00ac60..a0480c8554 100644 --- a/libopenage/renderer/gui/gui.cpp +++ b/libopenage/renderer/gui/gui.cpp @@ -104,8 +104,13 @@ void GUI::initialize_render_pass(size_t width, auto gl_pass = std::dynamic_pointer_cast(this->render_pass); if (gl_pass) { - gl_pass->set_stencil_config(true, true, 1, 0xFF, 0xFF, GL_ALWAYS); - } + renderer::opengl::StencilConfig config; + config.enabled = true; + config.write = true; + config.ref_value = 1; + config.test_func = GL_ALWAYS; + gl_pass->set_stencil_config(config); + } } diff --git a/libopenage/renderer/opengl/render_pass.cpp b/libopenage/renderer/opengl/render_pass.cpp index e043d4a1f8..7453b8ae55 100644 --- a/libopenage/renderer/opengl/render_pass.cpp +++ b/libopenage/renderer/opengl/render_pass.cpp @@ -36,13 +36,8 @@ void GlRenderPass::set_is_optimized(bool flag) { this->is_optimized = flag; } -void GlRenderPass::set_stencil_config(bool enabled, bool write, uint8_t ref_value, uint8_t write_mask, uint8_t read_mask, GLenum test_func) { - this->stencil_config.enabled = enabled; - this->stencil_config.write = write; - this->stencil_config.ref_value = ref_value; - this->stencil_config.write_mask = write_mask; - this->stencil_config.read_mask = read_mask; - this->stencil_config.test_func = test_func; +void GlRenderPass::set_stencil_config(const StencilConfig config) { + this->stencil_config = config; } const StencilConfig &GlRenderPass::get_stencil_config() const { diff --git a/libopenage/renderer/opengl/render_pass.h b/libopenage/renderer/opengl/render_pass.h index 0a779d673f..96da8c5a49 100644 --- a/libopenage/renderer/opengl/render_pass.h +++ b/libopenage/renderer/opengl/render_pass.h @@ -15,12 +15,18 @@ struct StencilConfig { bool write = false; /// Reference value for stencil test uint8_t ref_value = 1; + /// Stencil test function + GLenum test_func = GL_ALWAYS; /// Mask for writing to stencil buffer uint8_t write_mask = 0xFF; /// Mask for reading from stencil buffer uint8_t read_mask = 0xFF; - /// Stencil test function - GLenum test_func = GL_EQUAL; + /// Stencil operation for stencil fail + GLenum stencil_fail = GL_KEEP; + /// Stencil operation for depth fail + GLenum depth_fail = GL_KEEP; + /// Stencil operation for pass + GLenum depth_pass = GL_KEEP; }; class GlRenderPass final : public RenderPass { @@ -35,7 +41,7 @@ class GlRenderPass final : public RenderPass { void set_is_optimized(bool); bool get_is_optimized() const; - void set_stencil_config(bool enabled, bool write, uint8_t ref_value = 1, uint8_t write_mask = 0xFF, uint8_t read_mask = 0xFF, GLenum test_func = GL_EQUAL); + void set_stencil_config(const StencilConfig config); const StencilConfig &get_stencil_config() const; private: From dfa362d441e0eeb7b6e71fb40023f9b3eb713f6b Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Wed, 5 Feb 2025 09:44:51 -0500 Subject: [PATCH 10/14] fix tiny issues --- assets/test/shaders/demo_8_simple_gui.frag.glsl | 6 +++--- libopenage/renderer/opengl/renderer.cpp | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/assets/test/shaders/demo_8_simple_gui.frag.glsl b/assets/test/shaders/demo_8_simple_gui.frag.glsl index 16634353b5..c5a798c5b4 100644 --- a/assets/test/shaders/demo_8_simple_gui.frag.glsl +++ b/assets/test/shaders/demo_8_simple_gui.frag.glsl @@ -5,13 +5,13 @@ out vec4 fragColor; void main() { // Semi-transparent white color for the GUI - vec4 gui_color = vec4(1.0, 1.0, 1.0, 0.7); + vec4 gui_color = vec4(1.0, 1.0, 1.0, 1.0); // Add a border to make it look more like a GUI window float border = 0.05; if (v_uv.x < border || v_uv.x > 1.0 - border || v_uv.y < border || v_uv.y > 1.0 - border) { - gui_color = vec4(0.8, 0.8, 0.8, 0.9); // Darker border + gui_color = vec4(0.8, 0.8, 0.8, 1.0); // Darker border } fragColor = gui_color; -} \ No newline at end of file +} diff --git a/libopenage/renderer/opengl/renderer.cpp b/libopenage/renderer/opengl/renderer.cpp index 954c28caf9..f1811e2ab9 100644 --- a/libopenage/renderer/opengl/renderer.cpp +++ b/libopenage/renderer/opengl/renderer.cpp @@ -199,6 +199,7 @@ void GlRenderer::render(const std::shared_ptr &pass) { glEnable(GL_STENCIL_TEST); glStencilMask(stencil_config.write ? stencil_config.write_mask : 0x00); glStencilFunc(stencil_config.test_func, stencil_config.ref_value, stencil_config.read_mask); + glStencilOp(stencil_config.stencil_fail, stencil_config.depth_fail, stencil_config.depth_pass); } else { glDisable(GL_STENCIL_TEST); From 5933ab949a43039f40b83ebd6cff1d535508e11e Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Wed, 5 Feb 2025 09:45:36 -0500 Subject: [PATCH 11/14] update demo8 to make gui and background pass use the same fbo --- libopenage/renderer/demo/demo_8.cpp | 68 +++++++++++++++++++++-------- libopenage/renderer/demo/demo_8.h | 2 +- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/libopenage/renderer/demo/demo_8.cpp b/libopenage/renderer/demo/demo_8.cpp index f0d01d9492..292dddc394 100644 --- a/libopenage/renderer/demo/demo_8.cpp +++ b/libopenage/renderer/demo/demo_8.cpp @@ -1,4 +1,4 @@ -// Copyright 2023-2025 the openage authors. See copying.md for legal info. +// Copyright 2025-2025 the openage authors. See copying.md for legal info. #include "demo_8.h" @@ -45,7 +45,7 @@ void renderer_demo_8(const util::Path &path) { bg_fshader_file.read()); bg_fshader_file.close(); - // Load simple GUI quad shader from + // Load simple GUI quad shader (using a simple rectangle for GUI) auto gui_vshader_file = (shaderdir / "demo_8_simple_gui.vert.glsl").open(); auto gui_vshader_src = resources::ShaderSource( resources::shader_lang_t::glsl, @@ -60,13 +60,39 @@ void renderer_demo_8(const util::Path &path) { gui_fshader_file.read()); gui_fshader_file.close(); + // Load display shader + auto display_vshader_file = (shaderdir / "demo_1_display.vert.glsl").open(); + auto display_vshader_src = resources::ShaderSource( + resources::shader_lang_t::glsl, + resources::shader_stage_t::vertex, + display_vshader_file.read()); + display_vshader_file.close(); + + auto display_fshader_file = (shaderdir / "demo_1_display.frag.glsl").open(); + auto display_fshader_src = resources::ShaderSource( + resources::shader_lang_t::glsl, + resources::shader_stage_t::fragment, + display_fshader_file.read()); + display_fshader_file.close(); + auto bg_shader = renderer->add_shader({bg_vshader_src, bg_fshader_src}); auto gui_shader = renderer->add_shader({gui_vshader_src, gui_fshader_src}); + auto display_shader = renderer->add_shader({display_vshader_src, display_fshader_src}); auto quad = renderer->add_mesh_geometry(resources::MeshData::make_quad()); + auto color_texture = renderer->add_texture( + resources::Texture2dInfo( + settings.width, settings.height, resources::pixel_format::rgba8)); + + auto depth_stencil_texture = renderer->add_texture( + resources::Texture2dInfo( + settings.width, settings.height, resources::pixel_format::depth24_stencil8)); + auto fbo = renderer->create_texture_target({color_texture, depth_stencil_texture}); + auto bg_uniforms = bg_shader->new_uniform_input(); auto gui_uniforms = gui_shader->new_uniform_input(); + auto color_texture_uniform = display_shader->new_uniform_input("color_texture", color_texture); Renderable bg_obj{ bg_uniforms, @@ -78,38 +104,41 @@ void renderer_demo_8(const util::Path &path) { Renderable gui_obj{ gui_uniforms, quad, - true, // Enable alpha blending + false, false, // No depth test needed }; - auto depth_stencil_texture = renderer->add_texture( - resources::Texture2dInfo( - settings.width, settings.height, resources::pixel_format::depth24_stencil8)); - auto stencil_fbo = renderer->create_texture_target({depth_stencil_texture}); + Renderable display_obj{ + color_texture_uniform, + quad, + false, + false, + }; - //auto bg_pass = renderer->add_render_pass({bg_obj}, renderer->get_display_target()); - auto bg_pass = renderer->add_render_pass({bg_obj}, renderer->get_display_target()); - auto gui_pass = renderer->add_render_pass({gui_obj}, renderer->get_display_target()); - auto gui_stencil_pass = renderer->add_render_pass({gui_obj}, stencil_fbo); + // stencil pass for background and gui + auto bg_pass = renderer->add_render_pass({bg_obj}, fbo); + auto gui_pass = renderer->add_render_pass({gui_obj}, fbo); + // final output pass + auto display_pass = renderer->add_render_pass({display_obj}, renderer->get_display_target()); - // Configure stencil testing for background pass + // Configure stencil configurations auto gl_bg_pass = std::dynamic_pointer_cast(bg_pass); if (gl_bg_pass) { renderer::opengl::StencilConfig config; config.enabled = true; config.write = false; - config.ref_value = 1; + config.ref_value = 255; // get a white stencil mask in RenderDoc for debugging config.test_func = GL_NOTEQUAL; config.depth_pass = GL_KEEP; gl_bg_pass->set_stencil_config(config); } - auto gl_gui_stencil_pass = std::dynamic_pointer_cast(gui_stencil_pass); + auto gl_gui_stencil_pass = std::dynamic_pointer_cast(gui_pass); if (gl_gui_stencil_pass) { renderer::opengl::StencilConfig config; config.enabled = true; config.write = true; - config.ref_value = 1; + config.ref_value = 255; config.test_func = GL_ALWAYS; config.depth_pass = GL_REPLACE; gl_gui_stencil_pass->set_stencil_config(config); @@ -122,15 +151,18 @@ void renderer_demo_8(const util::Path &path) { float current_time = 0.0f; while (not window->should_close()) { + glClear(GL_STENCIL_BUFFER_BIT); + current_time += 0.01f; bg_uniforms->update("time", current_time); // Render background and GUI - renderer->render(gui_stencil_pass); + renderer->render(gui_pass); renderer->render(bg_pass); - renderer->render(gui_pass); + // Render display pass + renderer->render(display_pass); window->update(); qtapp->process_events(); @@ -140,4 +172,4 @@ void renderer_demo_8(const util::Path &path) { window->close(); } -} // namespace openage::renderer::tests \ No newline at end of file +} // namespace openage::renderer::tests diff --git a/libopenage/renderer/demo/demo_8.h b/libopenage/renderer/demo/demo_8.h index d05570cf6f..75bacf5474 100644 --- a/libopenage/renderer/demo/demo_8.h +++ b/libopenage/renderer/demo/demo_8.h @@ -1,4 +1,4 @@ -// Copyright 2023-2025 the openage authors. See copying.md for legal info. +// Copyright 2025-2025 the openage authors. See copying.md for legal info. #pragma once From 6f9c11d9d3e5184336c6389ee56a94e4388b1971 Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Wed, 5 Feb 2025 10:00:52 -0500 Subject: [PATCH 12/14] make stencil config setting outside of layer --- libopenage/renderer/opengl/renderer.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libopenage/renderer/opengl/renderer.cpp b/libopenage/renderer/opengl/renderer.cpp index f1811e2ab9..9d94da6e6c 100644 --- a/libopenage/renderer/opengl/renderer.cpp +++ b/libopenage/renderer/opengl/renderer.cpp @@ -190,21 +190,22 @@ void GlRenderer::render(const std::shared_ptr &pass) { const auto &renderables = gl_pass->get_renderables(); const auto &stencil_config = gl_pass->get_stencil_config(); + // Set stencil config + if (stencil_config.enabled) { + glEnable(GL_STENCIL_TEST); + glStencilMask(stencil_config.write ? stencil_config.write_mask : 0x00); + glStencilFunc(stencil_config.test_func, stencil_config.ref_value, stencil_config.read_mask); + glStencilOp(stencil_config.stencil_fail, stencil_config.depth_fail, stencil_config.depth_pass); + } + else { + glDisable(GL_STENCIL_TEST); + } + // Draw by layers for (size_t i = 0; i < layers.size(); i++) { const auto &layer = layers[i]; const auto &objects = renderables[i]; - if (stencil_config.enabled) { - glEnable(GL_STENCIL_TEST); - glStencilMask(stencil_config.write ? stencil_config.write_mask : 0x00); - glStencilFunc(stencil_config.test_func, stencil_config.ref_value, stencil_config.read_mask); - glStencilOp(stencil_config.stencil_fail, stencil_config.depth_fail, stencil_config.depth_pass); - } - else { - glDisable(GL_STENCIL_TEST); - } - if (layer.clear_depth) { glClear(GL_DEPTH_BUFFER_BIT); } From 2c790ce496a06ea00d8b0d64d2a945c8ed2b9c75 Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Wed, 5 Feb 2025 10:01:12 -0500 Subject: [PATCH 13/14] fix format issues --- libopenage/renderer/demo/demo_8.cpp | 2 +- libopenage/renderer/demo/demo_8.h | 4 ++-- libopenage/renderer/demo/tests.cpp | 2 +- libopenage/renderer/gui/gui.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libopenage/renderer/demo/demo_8.cpp b/libopenage/renderer/demo/demo_8.cpp index 292dddc394..7986c77df8 100644 --- a/libopenage/renderer/demo/demo_8.cpp +++ b/libopenage/renderer/demo/demo_8.cpp @@ -104,7 +104,7 @@ void renderer_demo_8(const util::Path &path) { Renderable gui_obj{ gui_uniforms, quad, - false, + false, false, // No depth test needed }; diff --git a/libopenage/renderer/demo/demo_8.h b/libopenage/renderer/demo/demo_8.h index 75bacf5474..7c8d184842 100644 --- a/libopenage/renderer/demo/demo_8.h +++ b/libopenage/renderer/demo/demo_8.h @@ -8,8 +8,8 @@ namespace openage::renderer::tests { /** * Show a demo of stencil testing. - * - GUI elements will create a stencil mask - * - Background will only render in non-GUI areas + * - GUI elements will create a stencil mask. + * - Background will only render in non-GUI areas. * * @param path Path to the project rootdir. */ diff --git a/libopenage/renderer/demo/tests.cpp b/libopenage/renderer/demo/tests.cpp index 58c21e848d..80d67b3d7e 100644 --- a/libopenage/renderer/demo/tests.cpp +++ b/libopenage/renderer/demo/tests.cpp @@ -1,4 +1,4 @@ -// Copyright 2015-2024 the openage authors. See copying.md for legal info. +// Copyright 2015-2025 the openage authors. See copying.md for legal info. #include "tests.h" diff --git a/libopenage/renderer/gui/gui.cpp b/libopenage/renderer/gui/gui.cpp index a0480c8554..c5b23f1213 100644 --- a/libopenage/renderer/gui/gui.cpp +++ b/libopenage/renderer/gui/gui.cpp @@ -110,7 +110,7 @@ void GUI::initialize_render_pass(size_t width, config.ref_value = 1; config.test_func = GL_ALWAYS; gl_pass->set_stencil_config(config); - } + } } From 23bf36d7d038b0c95bf75a1f88d4d6b2738d358d Mon Sep 17 00:00:00 2001 From: Alex Zhuohao He Date: Wed, 5 Feb 2025 10:09:22 -0500 Subject: [PATCH 14/14] disable depth test in bg to make stencil testi more visiable --- libopenage/renderer/demo/demo_8.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libopenage/renderer/demo/demo_8.cpp b/libopenage/renderer/demo/demo_8.cpp index 7986c77df8..d0c5bba110 100644 --- a/libopenage/renderer/demo/demo_8.cpp +++ b/libopenage/renderer/demo/demo_8.cpp @@ -98,14 +98,14 @@ void renderer_demo_8(const util::Path &path) { bg_uniforms, quad, false, - true, // Enable depth test + false, // Disable depth test to make stencil testing more visible }; Renderable gui_obj{ gui_uniforms, quad, false, - false, // No depth test needed + false, }; Renderable display_obj{