diff --git a/src/common/r_sequence.hpp b/src/common/r_sequence.hpp new file mode 100644 index 0000000..80b9b36 --- /dev/null +++ b/src/common/r_sequence.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "math.hpp" + +#include + +#include + +namespace nlrs +{ +inline glm::vec2 r2Sequence(const std::uint32_t n, const std::uint32_t sequenceLength) +{ + // https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences/ + constexpr float G = 1.32471795f; + constexpr float A1 = 1.0f / G; + constexpr float A2 = 1.0f / (G * G); + + const float i = static_cast(n % sequenceLength); + const float x = fract(0.5f + A1 * i); + const float y = fract(0.5f + A2 * i); + return glm::vec2(x, y); +} +} // namespace nlrs diff --git a/src/pt/deferred_renderer.cpp b/src/pt/deferred_renderer.cpp index 45efbc7..4214419 100644 --- a/src/pt/deferred_renderer.cpp +++ b/src/pt/deferred_renderer.cpp @@ -8,6 +8,7 @@ #include "window.hpp" #include +#include #include #include @@ -296,6 +297,7 @@ void DeferredRenderer::render( return wgpuDeviceCreateCommandEncoder(gpuContext.device, &cmdEncoderDesc); }(); + const Extent2f framebufferSize = Extent2f(renderDesc.framebufferSize); const std::uint32_t frameCount = mFrameCount++; // GBuffer pass @@ -311,6 +313,7 @@ void DeferredRenderer::render( mDepthTextureView, mAlbedoTextureView, mNormalTextureView, + framebufferSize, frameCount); wgpuCommandEncoderWriteTimestamp( encoder, @@ -323,7 +326,6 @@ void DeferredRenderer::render( encoder, mQuerySet, offsetof(TimestampsLayout, lightingPassStart) / TimestampsLayout::MEMBER_SIZE); - const Extent2f framebufferSize = Extent2f(renderDesc.framebufferSize); { const glm::mat4 inverseViewProjectionMat = glm::inverse(renderDesc.viewReverseZProjectionMatrix); @@ -456,6 +458,7 @@ void DeferredRenderer::renderDebug( mDepthTextureView, mAlbedoTextureView, mNormalTextureView, + framebufferSize, mFrameCount++); mDebugPass.render(gpuContext, encoder, textureView, framebufferSize, gui); @@ -1005,9 +1008,15 @@ void DeferredRenderer::GbufferPass::render( const WGPUTextureView depthTextureView, const WGPUTextureView albedoTextureView, const WGPUTextureView normalTextureView, - const std::uint32_t /*frameCount*/) + const Extent2f& framebufferSize, + const std::uint32_t frameCount) { - const Uniforms uniforms{viewReverseZProjectionMatrix}; + Uniforms uniforms{viewReverseZProjectionMatrix, glm::mat4(1.0f)}; + { + const glm::vec2 j = r2Sequence(frameCount, 1 << 20); + uniforms.jitterMat[3][0] = (j.x - 0.5f) / framebufferSize.x; + uniforms.jitterMat[3][1] = (j.y - 0.5f) / framebufferSize.y; + } wgpuQueueWriteBuffer(gpuContext.queue, mUniformBuffer.ptr(), 0, &uniforms, sizeof(Uniforms)); const WGPURenderPassEncoder renderPassEncoder = [cmdEncoder, diff --git a/src/pt/deferred_renderer.hpp b/src/pt/deferred_renderer.hpp index 8a8be43..3395fbb 100644 --- a/src/pt/deferred_renderer.hpp +++ b/src/pt/deferred_renderer.hpp @@ -109,6 +109,7 @@ class DeferredRenderer struct Uniforms { glm::mat4 viewProjectionMat; + glm::mat4 jitterMat; }; public: @@ -129,6 +130,7 @@ class DeferredRenderer WGPUTextureView depthTextureView, WGPUTextureView albedoTextureView, WGPUTextureView normalTextureView, + const Extent2f& framebufferSize, std::uint32_t frameCount); }; diff --git a/src/pt/deferred_renderer_gbuffer_pass.wgsl b/src/pt/deferred_renderer_gbuffer_pass.wgsl index 20c50d4..d81e28e 100644 --- a/src/pt/deferred_renderer_gbuffer_pass.wgsl +++ b/src/pt/deferred_renderer_gbuffer_pass.wgsl @@ -1,4 +1,9 @@ -@group(0) @binding(0) var viewReverseZProjectionMat: mat4x4f; +struct Uniforms { + viewReverseZProjectionMat: mat4x4f, + jitterMat: mat4x4f +} + +@group(0) @binding(0) var uniforms: Uniforms; struct VertexInput { @location(0) position: vec4f, @@ -15,7 +20,7 @@ struct VertexOutput { @vertex fn vsMain(in: VertexInput) -> VertexOutput { var out: VertexOutput; - out.position = viewReverseZProjectionMat * in.position; + out.position = uniforms.jitterMat * uniforms.viewReverseZProjectionMat * in.position; out.normal = in.normal; out.texCoord = in.texCoord; return out; diff --git a/src/pt/shader_source.hpp b/src/pt/shader_source.hpp index b10e698..98610dd 100644 --- a/src/pt/shader_source.hpp +++ b/src/pt/shader_source.hpp @@ -623,7 +623,12 @@ fn animatedBlueNoise(coord: vec2u, frameIdx: u32, totalSampleCount: u32) -> vec2 } )"; -const char* const DEFERRED_RENDERER_GBUFFER_PASS_SOURCE = R"(@group(0) @binding(0) var viewReverseZProjectionMat: mat4x4f; +const char* const DEFERRED_RENDERER_GBUFFER_PASS_SOURCE = R"(struct Uniforms { + viewReverseZProjectionMat: mat4x4f, + jitterMat: mat4x4f +} + +@group(0) @binding(0) var uniforms: Uniforms; struct VertexInput { @location(0) position: vec4f, @@ -640,7 +645,7 @@ struct VertexOutput { @vertex fn vsMain(in: VertexInput) -> VertexOutput { var out: VertexOutput; - out.position = viewReverseZProjectionMat * in.position; + out.position = uniforms.jitterMat * uniforms.viewReverseZProjectionMat * in.position; out.normal = in.normal; out.texCoord = in.texCoord; return out;