From 73a4587456178a2cf893ee15d12c52908e69e378 Mon Sep 17 00:00:00 2001 From: tomas7770 <77364520+tomas7770@users.noreply.github.com> Date: Thu, 4 Apr 2024 21:46:28 +0100 Subject: [PATCH] feat(rendering): add RenderPicker plugin --- CHANGELOG.md | 1 + engine/CMakeLists.txt | 3 + .../cubos/engine/render/picker/picker.hpp | 33 +++++++++++ .../cubos/engine/render/picker/plugin.hpp | 32 +++++++++++ engine/src/render/picker/picker.cpp | 12 ++++ engine/src/render/picker/plugin.cpp | 56 +++++++++++++++++++ 6 files changed, 137 insertions(+) create mode 100644 engine/include/cubos/engine/render/picker/picker.hpp create mode 100644 engine/include/cubos/engine/render/picker/plugin.hpp create mode 100644 engine/src/render/picker/picker.cpp create mode 100644 engine/src/render/picker/plugin.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index c5dc04a5a..c9f6cdf60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Addition and removal of resources through Commands (#325, **@RiscadoA**). - Access to unscaled delta time for utilities like the debug camera (#1020, **@RiscadoA**). - RenderTarget plugin (#1059, **@tomas7770**). +- RenderPicker plugin (#1060, **@tomas7770**). ### Changed diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 099fa391b..5aeb0a6df 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -109,6 +109,9 @@ set(CUBOS_ENGINE_SOURCE "src/render/target/plugin.cpp" "src/render/target/target.cpp" + + "src/render/picker/plugin.cpp" + "src/render/picker/picker.cpp" ) # Create cubos engine diff --git a/engine/include/cubos/engine/render/picker/picker.hpp b/engine/include/cubos/engine/render/picker/picker.hpp new file mode 100644 index 000000000..c897adb7c --- /dev/null +++ b/engine/include/cubos/engine/render/picker/picker.hpp @@ -0,0 +1,33 @@ +/// @file +/// @brief Component @ref cubos::engine::RenderPicker. +/// @ingroup render-picker-plugin + +#pragma once + +#include + +#include +#include + +namespace cubos::engine +{ + /// @brief Component which provides a texture to store entity/gizmo ids, for selection with a mouse. + /// @ingroup render-picker-plugin + struct RenderPicker + { + CUBOS_REFLECT; + + /// @brief Size of the RenderPicker textures, in pixels. + glm::uvec2 size = {0, 0}; + + /// @brief Picking back texture, stores entity/gizmo ids for each pixel on the screen. Access to the + /// picker results should be made through this texture, to ensure the CPU doesn't wait for the current frame + /// to finish. + core::gl::Texture2D backTexture{nullptr}; + + /// @brief Picking front texture, stores entity/gizmo ids for each pixel on the screen. This is the texture + /// used by the renderer to write ids. It is automatically swapped with the back texture by the + /// renderPickerPlugin. + core::gl::Texture2D frontTexture{nullptr}; + }; +} // namespace cubos::engine diff --git a/engine/include/cubos/engine/render/picker/plugin.hpp b/engine/include/cubos/engine/render/picker/plugin.hpp new file mode 100644 index 000000000..4ab875996 --- /dev/null +++ b/engine/include/cubos/engine/render/picker/plugin.hpp @@ -0,0 +1,32 @@ +/// @dir +/// @brief @ref render-picker-plugin plugin directory. + +/// @file +/// @brief Plugin entry point. +/// @ingroup render-picker-plugin + +#pragma once + +#include + +namespace cubos::engine +{ + /// @defgroup render-picker-plugin RenderPicker + /// @ingroup render-plugins + /// @brief Adds and manages @ref RenderPicker components. + /// + /// ## Dependencies + /// - @ref window-plugin + /// - @ref render-target-plugin + + /// @brief Recreates the RenderPicker if necessary - for example, due to a render target resize. + extern Tag createRenderPickerTag; + + /// @brief Systems which draw to RenderPicker textures should be tagged with this. + extern Tag drawToRenderPickerTag; + + /// @brief Plugin entry function. + /// @param cubos @b CUBOS. main class. + /// @ingroup render-picker-plugin + void renderPickerPlugin(Cubos& cubos); +} // namespace cubos::engine diff --git a/engine/src/render/picker/picker.cpp b/engine/src/render/picker/picker.cpp new file mode 100644 index 000000000..8385f43f4 --- /dev/null +++ b/engine/src/render/picker/picker.cpp @@ -0,0 +1,12 @@ +#include +#include +#include + +#include + +CUBOS_REFLECT_IMPL(cubos::engine::RenderPicker) +{ + return core::ecs::TypeBuilder("cubos::engine::RenderPicker") + .withField("size", &RenderPicker::size) + .build(); +} diff --git a/engine/src/render/picker/plugin.cpp b/engine/src/render/picker/plugin.cpp new file mode 100644 index 000000000..dc2c07549 --- /dev/null +++ b/engine/src/render/picker/plugin.cpp @@ -0,0 +1,56 @@ +#include +#include + +#include +#include +#include +#include +#include + +using cubos::core::gl::Texture2DDesc; +using cubos::core::gl::TextureFormat; +using cubos::core::gl::Usage; +using cubos::core::io::Window; + +CUBOS_DEFINE_TAG(cubos::engine::createRenderPickerTag); +CUBOS_DEFINE_TAG(cubos::engine::drawToRenderPickerTag); + +void cubos::engine::renderPickerPlugin(Cubos& cubos) +{ + cubos.depends(windowPlugin); + cubos.depends(renderTargetPlugin); + + cubos.component(); + + cubos.tag(createRenderPickerTag).after(resizeRenderTargetTag); + cubos.tag(drawToRenderPickerTag).after(createRenderPickerTag); + + cubos.system("resize RenderPickers") + .tagged(createRenderPickerTag) + .call([](const Window& window, Query query) { + for (auto [target, renderPicker] : query) + { + if (target.size != renderPicker.size) + { + renderPicker.size = target.size; + + // Prepare common texture description. + Texture2DDesc desc{}; + desc.width = renderPicker.size.x; + desc.height = renderPicker.size.y; + desc.usage = Usage::Dynamic; + desc.format = TextureFormat::RG16UInt; + + auto& rd = window->renderDevice(); + + renderPicker.backTexture = rd.createTexture2D(desc); + renderPicker.frontTexture = rd.createTexture2D(desc); + + CUBOS_INFO("Resized RenderPicker to {}x{}", renderPicker.size.x, renderPicker.size.y); + } + + // Swap textures + std::swap(renderPicker.backTexture, renderPicker.frontTexture); + } + }); +}