diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp index e39d7603f..c8975dba8 100644 --- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp +++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp @@ -462,7 +462,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext, ddgiData.Result.Constants.ProbesScrollOffsets[cascadeIndex] = Int4(cascade.ProbeScrollOffsets, 0); } ddgiData.Result.Constants.RayMaxDistance = 10000.0f; // TODO: adjust to match perf/quality ratio (make it based on Global SDF and Global Surface Atlas distance) - ddgiData.Result.Constants.ViewDir = renderContext.View.Direction; + ddgiData.Result.Constants.ViewPos = renderContext.View.Position; ddgiData.Result.Constants.RaysCount = probeRaysCount; ddgiData.Result.Constants.ProbeHistoryWeight = probeHistoryWeight; ddgiData.Result.Constants.IrradianceGamma = 5.0f; diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h index 48d16d643..af3d89083 100644 --- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h +++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h @@ -24,7 +24,7 @@ public: float RayMaxDistance; float IndirectLightingIntensity; Float4 RaysRotation; - Float3 ViewDir; + Float3 ViewPos; uint32 RaysCount; Float3 FallbackIrradiance; float Padding0; diff --git a/Source/Shaders/GI/DDGI.hlsl b/Source/Shaders/GI/DDGI.hlsl index 6b8345ea4..9b5101c6a 100644 --- a/Source/Shaders/GI/DDGI.hlsl +++ b/Source/Shaders/GI/DDGI.hlsl @@ -32,7 +32,7 @@ struct DDGIData float RayMaxDistance; float IndirectLightingIntensity; float4 RaysRotation; - float3 ViewDir; + float3 ViewPos; uint RaysCount; float3 FallbackIrradiance; float Padding0; @@ -120,8 +120,9 @@ float2 GetDDGIProbeUV(DDGIData data, uint cascadeIndex, uint probeIndex, float2 } // Samples DDGI probes volume at the given world-space position and returns the irradiance. -// rand - randomized per-pixel value in range 0-1, used to smooth dithering for cascades blending -float3 SampleDDGIIrradiance(DDGIData data, Texture2D probesState, Texture2D probesDistance, Texture2D probesIrradiance, float3 worldPosition, float3 worldNormal, float bias, float dither = 0.0f) +// bias - scales the bias vector to the initial sample point to reduce self-shading artifacts +// dither - randomized per-pixel value in range 0-1, used to smooth dithering for cascades blending +float3 SampleDDGIIrradiance(DDGIData data, Texture2D probesState, Texture2D probesDistance, Texture2D probesIrradiance, float3 worldPosition, float3 worldNormal, float bias = 0.2f, float dither = 0.0f) { // Select the highest cascade that contains the sample location uint cascadeIndex = 0; @@ -163,7 +164,8 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D probesState, float3 probesExtent = (data.ProbesCounts - 1) * (probesSpacing * 0.5f); // Bias the world-space position to reduce artifacts - float3 surfaceBias = (worldNormal * bias) + (data.ViewDir * (bias * -4.0f)); + float3 viewDir = normalize(data.ViewPos - worldPosition); + float3 surfaceBias = (worldNormal * 0.2f + viewDir * 0.8f) * (0.75f * probesSpacing * bias); float3 biasedWorldPosition = worldPosition + surfaceBias; // Get the grid coordinates of the probe nearest the biased world position @@ -190,7 +192,7 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D probesState, // Calculate the distance and direction from the (biased and non-biased) shading point and the probe float3 worldPosToProbe = normalize(probePosition - worldPosition); float3 biasedPosToProbe = normalize(probePosition - biasedWorldPosition); - float biasedPosToProbeDist = length(probePosition - biasedWorldPosition); + float biasedPosToProbeDist = length(probePosition - biasedWorldPosition) * 0.95f; // Smooth backface test float weight = Square(dot(worldPosToProbe, worldNormal) * 0.5f + 0.5f); diff --git a/Source/Shaders/GI/DDGI.shader b/Source/Shaders/GI/DDGI.shader index ebb6bff70..6ae11515d 100644 --- a/Source/Shaders/GI/DDGI.shader +++ b/Source/Shaders/GI/DDGI.shader @@ -387,7 +387,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_ // Load current probe value float3 previous = RWOutput[outputCoords].rgb; bool wasActivated = GetProbeState(probeState, DDGI_PROBE_STATE_ACTIVATED); - if (wasActivated) + if (ResetBlend || wasActivated) previous = float3(0, 0, 0); // Blend current value with the previous probe data @@ -522,7 +522,7 @@ void PS_IndirectLighting(Quad_VS2PS input, out float4 output : SV_Target0) } // Sample irradiance - float bias = 1.0f; + float bias = 0.2f; float dither = RandN2(input.TexCoord + TemporalTime).x; float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesState, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal, bias, dither); diff --git a/Source/Shaders/GI/GlobalSurfaceAtlas.shader b/Source/Shaders/GI/GlobalSurfaceAtlas.shader index f43332157..1c6c22571 100644 --- a/Source/Shaders/GI/GlobalSurfaceAtlas.shader +++ b/Source/Shaders/GI/GlobalSurfaceAtlas.shader @@ -125,7 +125,7 @@ float4 PS_Lighting(AtlasVertexOutput input) : SV_Target // Calculate lighting float3 diffuseColor = GetDiffuseColor(gBuffer); - diffuseColor = min(diffuseColor, 0.9f); // Nothing reflects diffuse like perfectly in the real world (ensure to have energy loss at each light bounce) + diffuseColor = min(diffuseColor, 0.98f); // Nothing reflects diffuse like perfectly in the real world (ensure to have energy loss at each light bounce) float3 diffuse = Diffuse_Lambert(diffuseColor); float4 light = float4(diffuse * irradiance * gBuffer.AO, 1); #else diff --git a/Source/Shaders/VolumetricFog.shader b/Source/Shaders/VolumetricFog.shader index 570802086..01756fe56 100644 --- a/Source/Shaders/VolumetricFog.shader +++ b/Source/Shaders/VolumetricFog.shader @@ -337,7 +337,7 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_ #if USE_DDGI // Dynamic Diffuse Global Illumination - float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesState, ProbesDistance, ProbesIrradiance, positionWS, cameraVectorNormalized, 1.0f); + float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesState, ProbesDistance, ProbesIrradiance, positionWS, cameraVectorNormalized, 0.0f, cellOffset.x); lightScattering += float4(irradiance, 1); #else // Sky light