From 29aa4553bc74348dc50ee05e043a40834060c31d Mon Sep 17 00:00:00 2001 From: Johann Muszynski Date: Fri, 28 Jun 2024 16:06:45 +0300 Subject: [PATCH] wip render to velocity buffer --- src/pt/deferred_renderer.cpp | 172 ++++++++++++++++----- src/pt/deferred_renderer.hpp | 18 ++- src/pt/deferred_renderer_debug_pass.wgsl | 11 +- src/pt/deferred_renderer_gbuffer_pass.wgsl | 19 ++- src/pt/shader_source.hpp | 30 ++-- 5 files changed, 185 insertions(+), 65 deletions(-) diff --git a/src/pt/deferred_renderer.cpp b/src/pt/deferred_renderer.cpp index e9d145e..2f39f47 100644 --- a/src/pt/deferred_renderer.cpp +++ b/src/pt/deferred_renderer.cpp @@ -22,6 +22,7 @@ namespace const WGPUTextureFormat DEPTH_TEXTURE_FORMAT = WGPUTextureFormat_Depth32Float; const WGPUTextureFormat ALBEDO_TEXTURE_FORMAT = WGPUTextureFormat_BGRA8Unorm; const WGPUTextureFormat NORMAL_TEXTURE_FORMAT = WGPUTextureFormat_RGBA16Float; +const WGPUTextureFormat VELOCITY_TEXTURE_FORMAT = WGPUTextureFormat_RG16Float; struct TimestampsLayout { @@ -96,6 +97,8 @@ DeferredRenderer::DeferredRenderer( mAlbedoTextureView(nullptr), mNormalTexture(nullptr), mNormalTextureView(nullptr), + mVelocityTexture(nullptr), + mVelocityTextureView(nullptr), mSampleBuffer( gpuContext.device, "Deferred renderer :: sample buffer", @@ -178,6 +181,18 @@ DeferredRenderer::DeferredRenderer( mNormalTexture, "Gbuffer normal texture view", NORMAL_TEXTURE_FORMAT); NLRS_ASSERT(mNormalTextureView != nullptr); + mVelocityTexture = createGbufferTexture( + gpuContext.device, + "Gbuffer velocity texture", + WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_TextureBinding, + rendererDesc.framebufferSize, + VELOCITY_TEXTURE_FORMAT); + NLRS_ASSERT(mVelocityTexture != nullptr); + + mVelocityTextureView = createGbufferTextureView( + mVelocityTexture, "Gbuffer velocity texture view", VELOCITY_TEXTURE_FORMAT); + NLRS_ASSERT(mVelocityTextureView != nullptr); + { const WGPUQuerySetDescriptor querySetDesc{ .nextInChain = nullptr, @@ -192,6 +207,7 @@ DeferredRenderer::DeferredRenderer( mAlbedoTextureView, mNormalTextureView, mDepthTextureView, + mVelocityTextureView, rendererDesc.framebufferSize}; mLightingPass = LightingPass{ gpuContext, @@ -210,6 +226,10 @@ DeferredRenderer::~DeferredRenderer() { querySetSafeRelease(mQuerySet); mQuerySet = nullptr; + textureViewSafeRelease(mVelocityTextureView); + mVelocityTextureView = nullptr; + textureSafeRelease(mVelocityTexture); + mVelocityTexture = nullptr; textureViewSafeRelease(mNormalTextureView); mNormalTextureView = nullptr; textureSafeRelease(mNormalTexture); @@ -240,6 +260,10 @@ DeferredRenderer::DeferredRenderer(DeferredRenderer&& other) other.mNormalTexture = nullptr; mNormalTextureView = other.mNormalTextureView; other.mNormalTextureView = nullptr; + mVelocityTexture = other.mVelocityTexture; + other.mVelocityTexture = nullptr; + mVelocityTextureView = other.mVelocityTextureView; + other.mVelocityTextureView = nullptr; mSampleBuffer = std::move(other.mSampleBuffer); mQuerySet = other.mQuerySet; other.mQuerySet = nullptr; @@ -271,6 +295,10 @@ DeferredRenderer& DeferredRenderer::operator=(DeferredRenderer&& other) other.mNormalTexture = nullptr; mNormalTextureView = other.mNormalTextureView; other.mNormalTextureView = nullptr; + mVelocityTexture = other.mVelocityTexture; + other.mVelocityTexture = nullptr; + mVelocityTextureView = other.mVelocityTextureView; + other.mVelocityTextureView = nullptr; mSampleBuffer = std::move(other.mSampleBuffer); mQuerySet = other.mQuerySet; other.mQuerySet = nullptr; @@ -308,7 +336,7 @@ void DeferredRenderer::render( const Extent2f framebufferSize = Extent2f(renderDesc.framebufferSize); const std::uint32_t frameCount = mFrameCount++; - const glm::mat4 jitterMat = jitterMatrix(framebufferSize, frameCount); + // const glm::mat4 jitterMat = jitterMatrix(framebufferSize, frameCount); // GBuffer pass @@ -318,12 +346,13 @@ void DeferredRenderer::render( offsetof(TimestampsLayout, gbufferPassStart) / TimestampsLayout::MEMBER_SIZE); mGbufferPass.render( gpuContext, - renderDesc.viewReverseZProjectionMatrix, - jitterMat, encoder, mDepthTextureView, mAlbedoTextureView, - mNormalTextureView); + mNormalTextureView, + mVelocityTextureView, + renderDesc.viewReverseZProjectionMatrix, + frameCount); wgpuCommandEncoderWriteTimestamp( encoder, mQuerySet, @@ -337,7 +366,7 @@ void DeferredRenderer::render( offsetof(TimestampsLayout, lightingPassStart) / TimestampsLayout::MEMBER_SIZE); { const glm::mat4 inverseViewProjectionMat = - glm::inverse(jitterMat * renderDesc.viewReverseZProjectionMatrix); + glm::inverse(renderDesc.viewReverseZProjectionMatrix); mLightingPass.render( gpuContext, encoder, @@ -461,16 +490,18 @@ void DeferredRenderer::renderDebug( return wgpuDeviceCreateCommandEncoder(gpuContext.device, &cmdEncoderDesc); }(); - const glm::mat4 jitterMat = jitterMatrix(framebufferSize, mFrameCount); + const std::uint32_t frameCount = mFrameCount++; + // const glm::mat4 jitterMat = jitterMatrix(framebufferSize, mFrameCount); mGbufferPass.render( gpuContext, - viewProjectionMat, - jitterMat, encoder, mDepthTextureView, mAlbedoTextureView, - mNormalTextureView); + mNormalTextureView, + mVelocityTextureView, + viewProjectionMat, + frameCount); mDebugPass.render(gpuContext, encoder, textureView, framebufferSize, gui); @@ -494,6 +525,8 @@ void DeferredRenderer::resize(const GpuContext& gpuContext, const Extent2u& newS textureSafeRelease(mAlbedoTexture); textureViewSafeRelease(mDepthTextureView); textureSafeRelease(mDepthTexture); + textureViewSafeRelease(mVelocityTextureView); + textureSafeRelease(mVelocityTexture); mNormalTextureView = nullptr; mNormalTexture = nullptr; @@ -501,6 +534,8 @@ void DeferredRenderer::resize(const GpuContext& gpuContext, const Extent2u& newS mAlbedoTexture = nullptr; mDepthTextureView = nullptr; mDepthTexture = nullptr; + mVelocityTextureView = nullptr; + mVelocityTexture = nullptr; { const std::array depthFormats{ @@ -543,7 +578,6 @@ void DeferredRenderer::resize(const GpuContext& gpuContext, const Extent2u& newS newSize, ALBEDO_TEXTURE_FORMAT); NLRS_ASSERT(mAlbedoTexture != nullptr); - mAlbedoTextureView = createGbufferTextureView( mAlbedoTexture, "Gbuffer albedo texture view", ALBEDO_TEXTURE_FORMAT); NLRS_ASSERT(mAlbedoTextureView != nullptr); @@ -555,12 +589,27 @@ void DeferredRenderer::resize(const GpuContext& gpuContext, const Extent2u& newS newSize, NORMAL_TEXTURE_FORMAT); NLRS_ASSERT(mNormalTexture != nullptr); - mNormalTextureView = createGbufferTextureView( mNormalTexture, "Gbuffer normal texture view", NORMAL_TEXTURE_FORMAT); NLRS_ASSERT(mNormalTextureView != nullptr); - mDebugPass.resize(gpuContext, mAlbedoTextureView, mNormalTextureView, mDepthTextureView); + mVelocityTexture = createGbufferTexture( + gpuContext.device, + "Gbuffer velocity texture", + WGPUTextureUsage_RenderAttachment | WGPUTextureUsage_TextureBinding, + newSize, + VELOCITY_TEXTURE_FORMAT); + NLRS_ASSERT(mVelocityTexture != nullptr); + mVelocityTextureView = createGbufferTextureView( + mVelocityTexture, "Gbuffer velocity texture view", VELOCITY_TEXTURE_FORMAT); + NLRS_ASSERT(mVelocityTextureView != nullptr); + + mDebugPass.resize( + gpuContext, + mAlbedoTextureView, + mNormalTextureView, + mDepthTextureView, + mVelocityTextureView); mLightingPass.resize(gpuContext, mAlbedoTextureView, mNormalTextureView, mDepthTextureView); } @@ -709,7 +758,8 @@ DeferredRenderer::GbufferPass::GbufferPass( sizeof(Uniforms)), mUniformBindGroup(), mSamplerBindGroup(), - mPipeline(nullptr) + mPipeline(nullptr), + mPreviousViewReverseZProjectionMat{glm::mat4(1.0f)} { const GpuBindGroupLayout uniformBindGroupLayout{ gpuContext.device, @@ -885,19 +935,40 @@ DeferredRenderer::GbufferPass::GbufferPass( .dstFactor = WGPUBlendFactor_One, }, }; + const WGPUBlendState noBlendState{ + .color = + WGPUBlendComponent{ + .operation = WGPUBlendOperation_Add, + .srcFactor = WGPUBlendFactor_One, + .dstFactor = WGPUBlendFactor_Zero, + }, + .alpha = + WGPUBlendComponent{ + .operation = WGPUBlendOperation_Undefined, + .srcFactor = WGPUBlendFactor_One, + .dstFactor = WGPUBlendFactor_Zero, + }, + }; - const std::array colorTargets{ - WGPUColorTargetState{ + const WGPUColorTargetState colorTargets[] = { + { .nextInChain = nullptr, .format = ALBEDO_TEXTURE_FORMAT, .blend = &blendState, .writeMask = WGPUColorWriteMask_All, }, - WGPUColorTargetState{ + { .nextInChain = nullptr, .format = NORMAL_TEXTURE_FORMAT, .blend = &blendState, - .writeMask = WGPUColorWriteMask_All}}; + .writeMask = WGPUColorWriteMask_All, + }, + { + .nextInChain = nullptr, + .format = VELOCITY_TEXTURE_FORMAT, + .blend = &noBlendState, + .writeMask = WGPUColorWriteMask_All, + }}; const WGPUFragmentState fragmentState{ .nextInChain = nullptr, @@ -905,8 +976,8 @@ DeferredRenderer::GbufferPass::GbufferPass( .entryPoint = "fsMain", .constantCount = 0, .constants = nullptr, - .targetCount = colorTargets.size(), - .targets = colorTargets.data(), + .targetCount = std::size(colorTargets), + .targets = colorTargets, }; // Pipeline @@ -986,6 +1057,7 @@ DeferredRenderer::GbufferPass::GbufferPass(GbufferPass&& other) noexcept mSamplerBindGroup = std::move(other.mSamplerBindGroup); mPipeline = other.mPipeline; other.mPipeline = nullptr; + mPreviousViewReverseZProjectionMat = other.mPreviousViewReverseZProjectionMat; } } @@ -1008,27 +1080,32 @@ DeferredRenderer::GbufferPass& DeferredRenderer::GbufferPass::operator=( mSamplerBindGroup = std::move(other.mSamplerBindGroup); mPipeline = other.mPipeline; other.mPipeline = nullptr; + mPreviousViewReverseZProjectionMat = other.mPreviousViewReverseZProjectionMat; } return *this; } void DeferredRenderer::GbufferPass::render( const GpuContext& gpuContext, - const glm::mat4& viewReverseZProjectionMatrix, - const glm::mat4& jitterMat, const WGPUCommandEncoder cmdEncoder, const WGPUTextureView depthTextureView, const WGPUTextureView albedoTextureView, - const WGPUTextureView normalTextureView) + const WGPUTextureView normalTextureView, + const WGPUTextureView velocityTextureView, + const glm::mat4& viewReverseZProjectionMatrix, + const std::uint32_t frameCount) { - const Uniforms uniforms{viewReverseZProjectionMatrix, jitterMat}; + const glm::mat4& previousViewReverseZProjectionMat = + frameCount == 0 ? viewReverseZProjectionMatrix : mPreviousViewReverseZProjectionMat; + const Uniforms uniforms{viewReverseZProjectionMatrix, previousViewReverseZProjectionMat}; wgpuQueueWriteBuffer(gpuContext.queue, mUniformBuffer.ptr(), 0, &uniforms, sizeof(Uniforms)); - const WGPURenderPassEncoder renderPassEncoder = [cmdEncoder, - depthTextureView, - albedoTextureView, - normalTextureView]() -> WGPURenderPassEncoder { - const std::array colorAttachments{ + mPreviousViewReverseZProjectionMat = viewReverseZProjectionMatrix; + + const WGPURenderPassEncoder renderPassEncoder = + [cmdEncoder, depthTextureView, albedoTextureView, normalTextureView, velocityTextureView]() + -> WGPURenderPassEncoder { + const WGPURenderPassColorAttachment colorAttachments[] = { WGPURenderPassColorAttachment{ .nextInChain = nullptr, .view = albedoTextureView, @@ -1045,8 +1122,15 @@ void DeferredRenderer::GbufferPass::render( .resolveTarget = nullptr, .loadOp = WGPULoadOp_Clear, .storeOp = WGPUStoreOp_Store, - .clearValue = WGPUColor{0.0, 0.0, 0.0, 1.0}, - }}; + .clearValue = WGPUColor{0.0, 0.0, 0.0, 1.0}}, + WGPURenderPassColorAttachment{ + .nextInChain = nullptr, + .view = velocityTextureView, + .depthSlice = WGPU_DEPTH_SLICE_UNDEFINED, + .resolveTarget = nullptr, + .loadOp = WGPULoadOp_Clear, + .storeOp = WGPUStoreOp_Store, + .clearValue = WGPUColor{0.0, 0.0, 0.0, 0.0}}}; const WGPURenderPassDepthStencilAttachment depthStencilAttachment{ .view = depthTextureView, @@ -1063,8 +1147,8 @@ void DeferredRenderer::GbufferPass::render( const WGPURenderPassDescriptor renderPassDesc = { .nextInChain = nullptr, .label = "Render pass encoder", - .colorAttachmentCount = colorAttachments.size(), - .colorAttachments = colorAttachments.data(), + .colorAttachmentCount = std::size(colorAttachments), + .colorAttachments = colorAttachments, .depthStencilAttachment = &depthStencilAttachment, .occlusionQuerySet = nullptr, .timestampWrites = nullptr, @@ -1118,6 +1202,7 @@ DeferredRenderer::DebugPass::DebugPass( const WGPUTextureView gbufferAlbedoTextureView, const WGPUTextureView gbufferNormalTextureView, const WGPUTextureView gbufferDepthTextureView, + const WGPUTextureView gbufferVelocityTextureView, const Extent2u& framebufferSize) : mVertexBuffer{gpuContext.device, "Vertex buffer", {GpuBufferUsage::Vertex, GpuBufferUsage::CopyDst}, std::span(quadVertexData)}, mUniformBuffer{}, @@ -1149,21 +1234,24 @@ DeferredRenderer::DebugPass::DebugPass( mGbufferBindGroupLayout = GpuBindGroupLayout{ gpuContext.device, "Debug pass gbuffer bind group layout", - std::array{ + std::array{ textureBindGroupLayoutEntry( 0, WGPUTextureSampleType_UnfilterableFloat, WGPUShaderStage_Fragment), textureBindGroupLayoutEntry( 1, WGPUTextureSampleType_UnfilterableFloat, WGPUShaderStage_Fragment), - textureBindGroupLayoutEntry(2, WGPUTextureSampleType_Depth, WGPUShaderStage_Fragment)}}; + textureBindGroupLayoutEntry(2, WGPUTextureSampleType_Depth, WGPUShaderStage_Fragment), + textureBindGroupLayoutEntry( + 3, WGPUTextureSampleType_UnfilterableFloat, WGPUShaderStage_Fragment)}}; mGbufferBindGroup = GpuBindGroup{ gpuContext.device, "Debug pass gbuffer bind group", mGbufferBindGroupLayout.ptr(), - std::array{ + std::array{ textureBindGroupEntry(0, gbufferAlbedoTextureView), textureBindGroupEntry(1, gbufferNormalTextureView), - textureBindGroupEntry(2, gbufferDepthTextureView)}}; + textureBindGroupEntry(2, gbufferDepthTextureView), + textureBindGroupEntry(3, gbufferVelocityTextureView)}}; { // Pipeline layout @@ -1378,16 +1466,18 @@ void DeferredRenderer::DebugPass::resize( const GpuContext& gpuContext, const WGPUTextureView albedoTextureView, const WGPUTextureView normalTextureView, - const WGPUTextureView depthTextureView) + const WGPUTextureView depthTextureView, + const WGPUTextureView velocityTextureView) { mGbufferBindGroup = GpuBindGroup{ gpuContext.device, "Debug pass gbuffer bind group", mGbufferBindGroupLayout.ptr(), - std::array{ + std::array{ textureBindGroupEntry(0, albedoTextureView), textureBindGroupEntry(1, normalTextureView), - textureBindGroupEntry(2, depthTextureView)}}; + textureBindGroupEntry(2, depthTextureView), + textureBindGroupEntry(3, velocityTextureView)}}; } DeferredRenderer::LightingPass::LightingPass( @@ -1501,8 +1591,8 @@ DeferredRenderer::LightingPass::LightingPass( textureData.reserve((2 << 28) / sizeof(Texture::BgraPixel)); // Texture descriptors and texture data need to appended in the order of - // sceneBaseColorTextures. The vertex attribute's `textureIdx` indexes into that array, and - // we want to use the same indices to index into the texture descriptor array. + // sceneBaseColorTextures. The vertex attribute's `textureIdx` indexes into that array, + // and we want to use the same indices to index into the texture descriptor array. for (const Texture& baseColorTexture : sceneBaseColorTextures) { diff --git a/src/pt/deferred_renderer.hpp b/src/pt/deferred_renderer.hpp index 840dfca..23c7575 100644 --- a/src/pt/deferred_renderer.hpp +++ b/src/pt/deferred_renderer.hpp @@ -105,11 +105,12 @@ class DeferredRenderer GpuBindGroup mUniformBindGroup{}; GpuBindGroup mSamplerBindGroup{}; WGPURenderPipeline mPipeline = nullptr; + glm::mat4 mPreviousViewReverseZProjectionMat{}; struct Uniforms { - glm::mat4 viewProjectionMat; - glm::mat4 jitterMat; + glm::mat4 currentViewReverseZProjectionMat; + glm::mat4 previousViewReverseZProjectionMat; }; public: @@ -125,12 +126,13 @@ class DeferredRenderer void render( const GpuContext& gpuContext, - const glm::mat4& viewProjectionMat, - const glm::mat4& jitterMat, WGPUCommandEncoder cmdEncoder, WGPUTextureView depthTextureView, WGPUTextureView albedoTextureView, - WGPUTextureView normalTextureView); + WGPUTextureView normalTextureView, + WGPUTextureView velocityTextureView, + const glm::mat4& viewProjectionMat, + std::uint32_t frameCount); }; struct DebugPass @@ -150,6 +152,7 @@ class DeferredRenderer WGPUTextureView albedoTextureView, WGPUTextureView normalTextureView, WGPUTextureView depthTextureView, + WGPUTextureView velocityTextureView, const Extent2u& framebufferSize); ~DebugPass(); @@ -169,7 +172,8 @@ class DeferredRenderer const GpuContext&, WGPUTextureView albedoTextureView, WGPUTextureView normalTextureView, - WGPUTextureView depthTextureView); + WGPUTextureView depthTextureView, + WGPUTextureView velocityTextureView); }; struct LightingPass @@ -282,6 +286,8 @@ class DeferredRenderer WGPUTextureView mAlbedoTextureView; WGPUTexture mNormalTexture; WGPUTextureView mNormalTextureView; + WGPUTexture mVelocityTexture; + WGPUTextureView mVelocityTextureView; GpuBuffer mSampleBuffer; WGPUQuerySet mQuerySet; GpuBuffer mQueryBuffer; diff --git a/src/pt/deferred_renderer_debug_pass.wgsl b/src/pt/deferred_renderer_debug_pass.wgsl index 492582f..8ff745d 100644 --- a/src/pt/deferred_renderer_debug_pass.wgsl +++ b/src/pt/deferred_renderer_debug_pass.wgsl @@ -21,21 +21,26 @@ fn vsMain(in: VertexInput) -> VertexOutput { @group(1) @binding(0) var gbufferAlbedo: texture_2d; @group(1) @binding(1) var gbufferNormal: texture_2d; @group(1) @binding(2) var gbufferDepth: texture_depth_2d; +@group(1) @binding(3) var gbufferVelocity: texture_2d; @fragment fn fsMain(in: VertexOutput) -> @location(0) vec4f { let c = in.texCoord; let idx = vec2u(floor(c * framebufferSize)); var rgb = vec3f(0f); - if c.x < 0.333 { + if c.x < 0.25 { rgb = textureLoad(gbufferAlbedo, idx, 0).rgb; - } else if c.x < 0.666 { + } else if c.x < 0.5 { rgb = textureLoad(gbufferNormal, idx, 0).rgb; - } else { + } else if c.x < 0.75 { let d = textureLoad(gbufferDepth, idx, 0); let x = d; let a = 0.1; rgb = vec3((1.0 + a) * x / (x + vec3(a))); + } else { + let uvVelocity = textureLoad(gbufferVelocity, idx, 0).rg; + let velocity = vec2(uvVelocity.x, 1.0 - uvVelocity.y); + rgb = vec3f(velocity, 0.0); } let srgb = pow(rgb, vec3(1.0 / 2.2)); return vec4(srgb, 1.0); diff --git a/src/pt/deferred_renderer_gbuffer_pass.wgsl b/src/pt/deferred_renderer_gbuffer_pass.wgsl index d81e28e..72dd520 100644 --- a/src/pt/deferred_renderer_gbuffer_pass.wgsl +++ b/src/pt/deferred_renderer_gbuffer_pass.wgsl @@ -1,6 +1,6 @@ struct Uniforms { - viewReverseZProjectionMat: mat4x4f, - jitterMat: mat4x4f + currentViewReverseZProjectionMat: mat4x4f, + previousViewReverseZProjectionMat: mat4x4f, } @group(0) @binding(0) var uniforms: Uniforms; @@ -13,14 +13,16 @@ struct VertexInput { struct VertexOutput { @builtin(position) position: vec4f, - @location(0) normal: vec4f, - @location(1) texCoord: vec2f, + @location(0) previousPosition: vec4f, + @location(1) normal: vec4f, + @location(2) texCoord: vec2f, } @vertex fn vsMain(in: VertexInput) -> VertexOutput { var out: VertexOutput; - out.position = uniforms.jitterMat * uniforms.viewReverseZProjectionMat * in.position; + out.position = uniforms.currentViewReverseZProjectionMat * in.position; + out.previousPosition = uniforms.previousViewReverseZProjectionMat * in.position; out.normal = in.normal; out.texCoord = in.texCoord; return out; @@ -32,11 +34,16 @@ fn vsMain(in: VertexInput) -> VertexOutput { struct GbufferOutput { @location(0) albedo: vec4, @location(1) normal: vec4, + @location(2) velocity: vec2, } @fragment fn fsMain(in: VertexOutput) -> GbufferOutput { let linearAlbedo = pow(textureSample(texture, textureSampler, in.texCoord).xyz, vec3(2.2f)); let encodedNormal = 0.5f * in.normal.xyz + vec3f(0.5f); - return GbufferOutput(vec4(linearAlbedo, 1f), vec4(encodedNormal, 1f)); + let currentNdc = in.position.xy / in.position.w; + let previousNdc = in.previousPosition.xy / in.previousPosition.w; + let ndcVelocity = previousNdc - currentNdc; // From the current pixel to the previous one + let uvVelocity = ndcVelocity * vec2f(0.5f, -0.5f) + vec2f(0.5f); + return GbufferOutput(vec4(linearAlbedo, 1f), vec4(encodedNormal, 1f), uvVelocity); } diff --git a/src/pt/shader_source.hpp b/src/pt/shader_source.hpp index 2bb0f50..bc2b48f 100644 --- a/src/pt/shader_source.hpp +++ b/src/pt/shader_source.hpp @@ -624,8 +624,8 @@ fn animatedBlueNoise(coord: vec2u, frameIdx: u32, totalSampleCount: u32) -> vec2 )"; const char* const DEFERRED_RENDERER_GBUFFER_PASS_SOURCE = R"(struct Uniforms { - viewReverseZProjectionMat: mat4x4f, - jitterMat: mat4x4f + currentViewReverseZProjectionMat: mat4x4f, + previousViewReverseZProjectionMat: mat4x4f, } @group(0) @binding(0) var uniforms: Uniforms; @@ -638,14 +638,16 @@ struct VertexInput { struct VertexOutput { @builtin(position) position: vec4f, - @location(0) normal: vec4f, - @location(1) texCoord: vec2f, + @location(0) previousPosition: vec4f, + @location(1) normal: vec4f, + @location(2) texCoord: vec2f, } @vertex fn vsMain(in: VertexInput) -> VertexOutput { var out: VertexOutput; - out.position = uniforms.jitterMat * uniforms.viewReverseZProjectionMat * in.position; + out.position = uniforms.currentViewReverseZProjectionMat * in.position; + out.previousPosition = uniforms.previousViewReverseZProjectionMat * in.position; out.normal = in.normal; out.texCoord = in.texCoord; return out; @@ -657,13 +659,18 @@ fn vsMain(in: VertexInput) -> VertexOutput { struct GbufferOutput { @location(0) albedo: vec4, @location(1) normal: vec4, + @location(2) velocity: vec2, } @fragment fn fsMain(in: VertexOutput) -> GbufferOutput { let linearAlbedo = pow(textureSample(texture, textureSampler, in.texCoord).xyz, vec3(2.2f)); let encodedNormal = 0.5f * in.normal.xyz + vec3f(0.5f); - return GbufferOutput(vec4(linearAlbedo, 1f), vec4(encodedNormal, 1f)); + let currentNdc = in.position.xy / in.position.w; + let previousNdc = in.previousPosition.xy / in.previousPosition.w; + let ndcVelocity = previousNdc - currentNdc; // From the current pixel to the previous one + let uvVelocity = ndcVelocity * vec2f(0.5f, -0.5f) + vec2f(0.5f); + return GbufferOutput(vec4(linearAlbedo, 1f), vec4(encodedNormal, 1f), uvVelocity); } )"; @@ -690,21 +697,26 @@ fn vsMain(in: VertexInput) -> VertexOutput { @group(1) @binding(0) var gbufferAlbedo: texture_2d; @group(1) @binding(1) var gbufferNormal: texture_2d; @group(1) @binding(2) var gbufferDepth: texture_depth_2d; +@group(1) @binding(3) var gbufferVelocity: texture_2d; @fragment fn fsMain(in: VertexOutput) -> @location(0) vec4f { let c = in.texCoord; let idx = vec2u(floor(c * framebufferSize)); var rgb = vec3f(0f); - if c.x < 0.333 { + if c.x < 0.25 { rgb = textureLoad(gbufferAlbedo, idx, 0).rgb; - } else if c.x < 0.666 { + } else if c.x < 0.5 { rgb = textureLoad(gbufferNormal, idx, 0).rgb; - } else { + } else if c.x < 0.75 { let d = textureLoad(gbufferDepth, idx, 0); let x = d; let a = 0.1; rgb = vec3((1.0 + a) * x / (x + vec3(a))); + } else { + let uvVelocity = textureLoad(gbufferVelocity, idx, 0).rg; + let velocity = vec2(uvVelocity.x, 1.0 - uvVelocity.y); + rgb = vec3f(velocity, 0.0); } let srgb = pow(rgb, vec3(1.0 / 2.2)); return vec4(srgb, 1.0);