diff --git a/Source/Engine/Level/Actors/Light.h b/Source/Engine/Level/Actors/Light.h index f8bb353f1..63b78a6b3 100644 --- a/Source/Engine/Level/Actors/Light.h +++ b/Source/Engine/Level/Actors/Light.h @@ -162,7 +162,7 @@ public: /// /// The length of the rays for contact shadows computed via the screen-space tracing. Set this to values higher than 0 to enable screen-space shadows rendering for this light. This improves the shadowing details. Actual ray distance is based on the pixel distance from the camera. /// - API_FIELD(Attributes="EditorOrder(99), EditorDisplay(\"Shadow\"), Limit(0.0f, 0.1f, 0.001f)") + API_FIELD(Attributes="EditorOrder(99), EditorDisplay(\"Shadow\"), Limit(0.0f, 0.4f, 0.001f)") float ContactShadowsLength = 0.0f; /// diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index 7065e33dd..a3fd7d625 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -34,7 +34,7 @@ GPU_CB_STRUCT(Data { ShaderLightData Light; Matrix WVP; Matrix ViewProjectionMatrix; - float Dummy0; + uint32 FrameIndexMod8; float TemporalTime; float ContactShadowsDistance; float ContactShadowsLength; @@ -1718,6 +1718,7 @@ void ShadowsPass::RenderShadowMask(RenderContextBatch& renderContextBatch, Rende else if (light.IsSpotLight) ((RenderSpotLightData&)light).SetShaderData(sperLight.Light, true); Matrix::Transpose(view.ViewProjection(), sperLight.ViewProjectionMatrix); + sperLight.FrameIndexMod8 = renderContext.List->Setup.UseTemporalAAJitter ? (int32)(Engine::FrameCount % 8) : 0; sperLight.TemporalTime = renderContext.List->Setup.UseTemporalAAJitter ? RenderTools::ComputeTemporalTime() : 0.0f; sperLight.ContactShadowsDistance = light.ShadowsDistance; sperLight.ContactShadowsLength = EnumHasAnyFlags(view.Flags, ViewFlags::ContactShadows) ? light.ContactShadowsLength : 0.0f; diff --git a/Source/Shaders/GI/DDGI.shader b/Source/Shaders/GI/DDGI.shader index 6c4e65572..4e3541554 100644 --- a/Source/Shaders/GI/DDGI.shader +++ b/Source/Shaders/GI/DDGI.shader @@ -863,7 +863,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_ result = float4(lerp(result.rgb, previous.rgb, historyWeight), 1.0f); // Apply quantization error to reduce yellowish artifacts due to R11G11B10 format - float noise = InterleavedGradientNoise(octahedralCoords, FrameIndexMod8); + float noise = InterleavedGradientNoise(octahedralCoords * 10, FrameIndexMod8); result.rgb = QuantizeColor(result.rgb, noise, QuantizationError); #else result = float4(lerp(result.rg, previous.rg, historyWeight), 0.0f, 1.0f); diff --git a/Source/Shaders/Shadows.shader b/Source/Shaders/Shadows.shader index 7f5b81511..c7f3e6741 100644 --- a/Source/Shaders/Shadows.shader +++ b/Source/Shaders/Shadows.shader @@ -13,7 +13,7 @@ GBufferData GBuffer; LightData Light; float4x4 WVP; float4x4 ViewProjectionMatrix; -float Dummy0; +uint FrameIndexMod8; float TemporalTime; float ContactShadowsDistance; float ContactShadowsLength; @@ -26,7 +26,9 @@ DECLARE_GBUFFERDATA_ACCESS(GBuffer) #if CONTACT_SHADOWS -float RayCastScreenSpaceShadow(GBufferData gBufferData, GBufferSample gBuffer, float3 rayStartWS, float3 rayDirWS, float rayLength) +#include "./Flax/Noise.hlsl" + +float RayCastScreenSpaceShadow(GBufferData gBufferData, GBufferSample gBuffer, float3 rayStartWS, float3 rayDirWS, float rayLength, float dither = 0.5f) { uint2 depthSize; Depth.GetDimensions(depthSize.x, depthSize.y); @@ -53,7 +55,7 @@ float RayCastScreenSpaceShadow(GBufferData gBufferData, GBufferSample gBuffer, f float rayStepDstMin = min(rayStepDst.x, rayStepDst.y); float3 rayStepMin = raySize / max(min(maxSteps, rayStepDstMin), 1); float3 rayStep = raySize / maxSteps; - float3 ray = rayStart + rayStepMin * 1.5f; + float3 ray = rayStart + rayStepMin * (dither * 2 + 1.0f); // Sample over the ray float lightAmountMax = 0; @@ -113,8 +115,10 @@ float4 PS_DirLight(Quad_VS2PS input) : SV_Target0 ShadowSample shadow = SampleDirectionalLightShadow(Light, ShadowsBuffer, ShadowMap, gBuffer, TemporalTime); #if CONTACT_SHADOWS - // Calculate screen-space contact shadow - shadow.SurfaceShadow *= RayCastScreenSpaceShadow(gBufferData, gBuffer, gBuffer.WorldPos, Light.Direction, ContactShadowsLength); + // Calculate screen-space contact shadow + float dither = InterleavedGradientNoise(input.Position.xy, FrameIndexMod8); + float contactShadow = RayCastScreenSpaceShadow(gBufferData, gBuffer, gBuffer.WorldPos, Light.Direction, ContactShadowsLength, dither); + shadow.SurfaceShadow = min(shadow.SurfaceShadow, contactShadow); #endif return GetShadowMask(shadow); @@ -155,8 +159,10 @@ float4 PS_LocalLight(Model_VS2PS input) : SV_Target0 #endif #if CONTACT_SHADOWS - // Calculate screen-space contact shadow - shadow.SurfaceShadow *= RayCastScreenSpaceShadow(gBufferData, gBuffer, gBuffer.WorldPos, normalize(Light.Position - gBuffer.WorldPos), ContactShadowsLength); + // Calculate screen-space contact shadow + float dither = InterleavedGradientNoise(input.ScreenPos.xy, FrameIndexMod8); + float contactShadow = RayCastScreenSpaceShadow(gBufferData, gBuffer, gBuffer.WorldPos, normalize(Light.Position - gBuffer.WorldPos), ContactShadowsLength, dither); + shadow.SurfaceShadow = min(shadow.SurfaceShadow, contactShadow); #endif return GetShadowMask(shadow);