Add temporal dithering and more accurate blending for contact shadows
This commit is contained in:
@@ -162,7 +162,7 @@ public:
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
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;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user