From 4b4da14b932ee0843b990bd4e4c50430a2539f17 Mon Sep 17 00:00:00 2001 From: tomas7770 <77364520+tomas7770@users.noreply.github.com> Date: Sun, 22 Dec 2024 13:02:49 +0000 Subject: [PATCH] feat(rendering): add SSAO resolution scale --- CHANGELOG.md | 4 +++ engine/assets/render/ssao_blur.fs | 4 ++- .../include/cubos/engine/render/ssao/ssao.hpp | 3 ++ engine/src/render/ssao/plugin.cpp | 29 +++++++++++++++---- engine/src/render/ssao/ssao.cpp | 1 + 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e7034b9cf..81597d0d23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- SSAO resolution scale (#1423, **@tomas7770**). + ### Changed - Make SSAO optional (#1396, **@tomas7770**). diff --git a/engine/assets/render/ssao_blur.fs b/engine/assets/render/ssao_blur.fs index 83b7e0b06a..f3e227969b 100644 --- a/engine/assets/render/ssao_blur.fs +++ b/engine/assets/render/ssao_blur.fs @@ -5,11 +5,13 @@ uniform sampler2D ssaoTexture; uniform vec2 viewportOffset; uniform vec2 viewportSize; +uniform float resolutionScale; + layout (location = 0) out float color; void main() { vec2 uv = fragUv * viewportSize + viewportOffset; - vec2 texelSize = 1.0 / vec2(textureSize(ssaoTexture, 0)); + vec2 texelSize = resolutionScale / vec2(textureSize(ssaoTexture, 0)); float result = 0.0; for (int x = -2; x < 2; ++x) { diff --git a/engine/include/cubos/engine/render/ssao/ssao.hpp b/engine/include/cubos/engine/render/ssao/ssao.hpp index b831a932f7..690e879414 100644 --- a/engine/include/cubos/engine/render/ssao/ssao.hpp +++ b/engine/include/cubos/engine/render/ssao/ssao.hpp @@ -22,6 +22,9 @@ namespace cubos::engine /// @brief Size of the SSAO textures, in pixels. glm::uvec2 size = {0, 0}; + /// @brief Scale value to configure SSAO texture size. + float resolutionScale = 0.5F; + /// @brief Number of samples to use. int samples = 64; diff --git a/engine/src/render/ssao/plugin.cpp b/engine/src/render/ssao/plugin.cpp index 761be6aaba..cedee2b9b1 100644 --- a/engine/src/render/ssao/plugin.cpp +++ b/engine/src/render/ssao/plugin.cpp @@ -29,6 +29,7 @@ using cubos::core::io::Window; CUBOS_DEFINE_TAG(cubos::engine::drawToSSAOTag); #define MAX_KERNEL_SIZE 64 +#define MAX_SSAO_RESOLUTION 2.0F namespace { @@ -60,6 +61,7 @@ namespace ShaderBindingPoint blurSSAOBP; ShaderBindingPoint blurViewportOffsetBP; ShaderBindingPoint blurViewportSizeBP; + ShaderBindingPoint blurResolutionScaleBP; VertexArray blurScreenQuad; ConstantBuffer perSceneCB; @@ -86,8 +88,9 @@ namespace blurSSAOBP = blurPipeline->getBindingPoint("ssaoTexture"); blurViewportOffsetBP = blurPipeline->getBindingPoint("viewportOffset"); blurViewportSizeBP = blurPipeline->getBindingPoint("viewportSize"); - CUBOS_ASSERT(blurSSAOBP && blurViewportOffsetBP && blurViewportSizeBP, - "ssaoTexture, viewportOffset and viewportSize binding points must exist"); + blurResolutionScaleBP = blurPipeline->getBindingPoint("resolutionScale"); + CUBOS_ASSERT(blurSSAOBP && blurViewportOffsetBP && blurViewportSizeBP && blurResolutionScaleBP, + "ssaoTexture, viewportOffset, viewportSize and resolutionScale binding points must exist"); generateScreenQuad(renderDevice, blurPipeline, blurScreenQuad); perSceneCB = renderDevice.createConstantBuffer(sizeof(PerScene), nullptr, Usage::Dynamic); @@ -197,15 +200,28 @@ void cubos::engine::ssaoPlugin(Cubos& cubos) } // Check if we need to resize the SSAO textures. - if (ssao.size != gBuffer.size) + if (ssao.resolutionScale > MAX_SSAO_RESOLUTION) { - ssao.size = gBuffer.size; + // There's probably not much benefit to a scale larger than 1.0, so don't allow very large scale + CUBOS_WARN("SSAO resolution scale is too large, clamping to {}", MAX_SSAO_RESOLUTION); + ssao.resolutionScale = MAX_SSAO_RESOLUTION; + } + else if (ssao.resolutionScale <= 0.0F) + { + CUBOS_WARN("SSAO resolution scale must be positive, setting to 0.5"); + ssao.resolutionScale = 0.5F; + } + auto ssaoConfigSize = glm::uvec2(float(gBuffer.size.x) * ssao.resolutionScale, + float(gBuffer.size.y) * ssao.resolutionScale); + if (ssao.size != ssaoConfigSize) + { + ssao.size = ssaoConfigSize; // Prepare common texture description. Texture2DDesc desc{}; desc.format = TextureFormat::R32Float; - desc.width = gBuffer.size.x; - desc.height = gBuffer.size.y; + desc.width = ssao.size.x; + desc.height = ssao.size.y; desc.usage = Usage::Dynamic; // Create base and blur textures. @@ -268,6 +284,7 @@ void cubos::engine::ssaoPlugin(Cubos& cubos) state.blurSSAOBP->bind(ssao.baseTexture); state.blurViewportOffsetBP->setConstant(drawsTo.viewportOffset); state.blurViewportSizeBP->setConstant(drawsTo.viewportSize); + state.blurResolutionScaleBP->setConstant(ssao.resolutionScale); rd.setVertexArray(state.blurScreenQuad); rd.drawTriangles(0, 6); } diff --git a/engine/src/render/ssao/ssao.cpp b/engine/src/render/ssao/ssao.cpp index 44c17fcd1c..86f188a952 100644 --- a/engine/src/render/ssao/ssao.cpp +++ b/engine/src/render/ssao/ssao.cpp @@ -8,6 +8,7 @@ CUBOS_REFLECT_IMPL(cubos::engine::SSAO) { return core::ecs::TypeBuilder("cubos::engine::SSAO") .withField("size", &SSAO::size) + .withField("resolutionScale", &SSAO::resolutionScale) .withField("samples", &SSAO::samples) .withField("radius", &SSAO::radius) .withField("bias", &SSAO::bias)