From d2d7a871ce88e7e51d2b4791af54f26a3af6cae5 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 14 Jan 2026 14:00:54 +0100 Subject: [PATCH] Add sharpening and better AABB history clamp to Screen Space Reflections temporal filter --- .../Renderer/ScreenSpaceReflectionsPass.cpp | 6 ---- Source/Shaders/SSR.shader | 36 ++++++++----------- Source/Shaders/TAA.shader | 13 +------ Source/Shaders/Temporal.hlsl | 19 ++++++++++ 4 files changed, 35 insertions(+), 39 deletions(-) create mode 100644 Source/Shaders/Temporal.hlsl diff --git a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp index 454540eec..ab772a0d3 100644 --- a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp +++ b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp @@ -24,29 +24,23 @@ GPU_CB_STRUCT(Data { ShaderGBufferData GBuffer; - float MaxColorMiplevel; float TraceSizeMax; float MaxTraceSamples; float RoughnessFade; - Float2 SSRtexelSize; float TemporalTime; float BRDFBias; - float WorldAntiSelfOcclusionBias; float EdgeFadeFactor; float TemporalResponse; float TemporalScale; - float RayTraceStep; float TemporalEffect; float Intensity; float FadeOutDistance; - Matrix ViewMatrix; Matrix ViewProjectionMatrix; - GlobalSignDistanceFieldPass::ConstantsData GlobalSDF; GlobalSurfaceAtlasPass::ConstantsData GlobalSurfaceAtlas; }); diff --git a/Source/Shaders/SSR.shader b/Source/Shaders/SSR.shader index 734c40346..6fffbd2c6 100644 --- a/Source/Shaders/SSR.shader +++ b/Source/Shaders/SSR.shader @@ -5,6 +5,7 @@ #include "./Flax/ReflectionsCommon.hlsl" #include "./Flax/SSR.hlsl" #include "./Flax/GBuffer.hlsl" +#include "./Flax/Temporal.hlsl" #include "./Flax/GlobalSignDistanceField.hlsl" #include "./Flax/GI/GlobalSurfaceAtlas.hlsl" @@ -15,34 +16,26 @@ #define SSR_MIX_BLUR 1 META_CB_BEGIN(0, Data) - GBufferData GBuffer; - float MaxColorMiplevel; float TraceSizeMax; float MaxTraceSamples; float RoughnessFade; - float2 SSRtexelSize; float TemporalTime; float BRDFBias; - float WorldAntiSelfOcclusionBias; float EdgeFadeFactor; float TemporalResponse; float TemporalScale; - float RayTraceStep; float TemporalEffect; float Intensity; float FadeOutDistance; - float4x4 ViewMatrix; float4x4 ViewProjectionMatrix; - GlobalSDFData GlobalSDF; GlobalSurfaceAtlasData GlobalSurfaceAtlas; - META_CB_END DECLARE_GBUFFERDATA_ACCESS(GBuffer) @@ -227,15 +220,11 @@ float4 PS_TemporalPass(Quad_VS2PS input) : SV_Target0 // Texture1 - prev frame temporal SSR buffer // Texture2 - motion vectors + // Sample inputss float2 uv = input.TexCoord; - - // Sample velocity float2 velocity = Texture2.SampleLevel(SamplerLinearClamp, uv, 0).xy; - - // Prepare float2 prevUV = uv - velocity; float4 current = Texture0.SampleLevel(SamplerLinearClamp, uv, 0); - float4 previous = Texture1.SampleLevel(SamplerLinearClamp, prevUV, 0); float2 du = float2(SSRtexelSize.x, 0.0); float2 dv = float2(0.0, SSRtexelSize.y); @@ -252,18 +241,23 @@ float4 PS_TemporalPass(Quad_VS2PS input) : SV_Target0 float4 currentMin = min(currentTopLeft, min(currentTopCenter, min(currentTopRight, min(currentMiddleLeft, min(currentMiddleCenter, min(currentMiddleRight, min(currentBottomLeft, min(currentBottomCenter, currentBottomRight)))))))); float4 currentMax = max(currentTopLeft, max(currentTopCenter, max(currentTopRight, max(currentMiddleLeft, max(currentMiddleCenter, max(currentMiddleRight, max(currentBottomLeft, max(currentBottomCenter, currentBottomRight)))))))); + float4 currentSum = currentTopLeft + currentTopCenter + currentTopRight + currentMiddleLeft + currentMiddleCenter + currentMiddleRight + currentBottomLeft + currentBottomCenter + currentBottomRight; + float4 currentAvg = currentSum / 9.0; - float scale = TemporalScale; + // Sample history by clamp it to the nearby colors range to reduce artifacts + float lumaOffset = abs(Luminance(currentAvg.rgb) - Luminance(current.rgb)); + float velocityLength = length(velocity); + float aabbMargin = lerp(4.0, 0.25, saturate(velocityLength * 100.0)) * lumaOffset; + float4 previous = Texture1.SampleLevel(SamplerLinearClamp, prevUV, 0); + previous = ClipToAABB(previous, currentMin - aabbMargin, currentMax + aabbMargin); + //previous = clamp(previous, currentMin, currentMax); - float4 center = (currentMin + currentMax) * 0.5f; - currentMin = (currentMin - center) * scale + center; - currentMax = (currentMax - center) * scale + center; - - previous = clamp(previous, currentMin, currentMax); + // Blend with history sample + float response = TemporalResponse * (1 - velocityLength * 8); + current = lerp(current, previous, saturate(response)); current = clamp(current, 0, HDR_CLAMP_MAX); - float response = TemporalResponse * (1 - length(velocity) * 8); - return lerp(current, previous, saturate(response)); + return current; } // Pixel Shader for screen space reflections rendering - mix pass diff --git a/Source/Shaders/TAA.shader b/Source/Shaders/TAA.shader index ca100b92c..89bda3baa 100644 --- a/Source/Shaders/TAA.shader +++ b/Source/Shaders/TAA.shader @@ -6,6 +6,7 @@ #include "./Flax/Common.hlsl" #include "./Flax/GBuffer.hlsl" #include "./Flax/Noise.hlsl" +#include "./Flax/Temporal.hlsl" META_CB_BEGIN(0, Data) float2 ScreenSizeInv; @@ -24,17 +25,6 @@ Texture2D InputHistory : register(t1); Texture2D MotionVectors : register(t2); Texture2D Depth : register(t3); -// [Pedersen, 2016, "Temporal Reprojection Anti-Aliasing in INSIDE"] -float4 ClipToAABB(float4 color, float4 minimum, float4 maximum) -{ - float4 center = (maximum + minimum) * 0.5; - float4 extents = (maximum - minimum) * 0.5; - float4 shift = color - center; - float4 absUnit = abs(shift / max(extents, 0.0001)); - float maxUnit = max(max(absUnit.x, absUnit.y), absUnit.z); - return maxUnit > 1.0 ? center + (shift / maxUnit) : color; -} - // Pixel Shader for Temporal Anti-Aliasing META_PS(true, FEATURE_LEVEL_ES2) float4 PS(Quad_VS2PS input) : SV_Target0 @@ -105,7 +95,6 @@ float4 PS(Quad_VS2PS input) : SV_Target0 neighborhoodSharp = float4(1, 0, 0, 1); #endif color = lerp(color, neighborhoodSharp, saturate(miss)); - color = clamp(color, 0, HDR_CLAMP_MAX); // Apply quantization error to reduce yellowish artifacts due to R11G11B10 format diff --git a/Source/Shaders/Temporal.hlsl b/Source/Shaders/Temporal.hlsl new file mode 100644 index 000000000..8c32253e6 --- /dev/null +++ b/Source/Shaders/Temporal.hlsl @@ -0,0 +1,19 @@ +// Copyright (c) Wojciech Figat. All rights reserved. + +#ifndef __TEMPORAL__ +#define __TEMPORAL__ + +#include "./Flax/Common.hlsl" + +// [Pedersen, 2016, "Temporal Reprojection Anti-Aliasing in INSIDE"] +float4 ClipToAABB(float4 color, float4 minimum, float4 maximum) +{ + float4 center = (maximum + minimum) * 0.5; + float4 extents = (maximum - minimum) * 0.5; + float4 shift = color - center; + float4 absUnit = abs(shift / max(extents, 0.0001)); + float maxUnit = max(max(absUnit.x, absUnit.y), absUnit.z); + return maxUnit > 1.0 ? center + (shift / maxUnit) : color; +} + +#endif