Improve GI quality
This commit is contained in:
BIN
Content/Editor/DebugMaterials/DDGIDebugProbes.flax
(Stored with Git LFS)
BIN
Content/Editor/DebugMaterials/DDGIDebugProbes.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/GI/DDGI.flax
(Stored with Git LFS)
BIN
Content/Shaders/GI/DDGI.flax
(Stored with Git LFS)
Binary file not shown.
BIN
Content/Shaders/GI/GlobalSurfaceAtlas.flax
(Stored with Git LFS)
BIN
Content/Shaders/GI/GlobalSurfaceAtlas.flax
(Stored with Git LFS)
Binary file not shown.
@@ -43,7 +43,8 @@ PACK_STRUCT(struct Data0
|
||||
GlobalSignDistanceFieldPass::ConstantsData GlobalSDF;
|
||||
GlobalSurfaceAtlasPass::ConstantsData GlobalSurfaceAtlas;
|
||||
GBufferData GBuffer;
|
||||
Vector3 Padding0;
|
||||
Vector2 Padding0;
|
||||
float ResetBlend;
|
||||
float IndirectLightingIntensity;
|
||||
});
|
||||
|
||||
@@ -283,7 +284,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
|
||||
|
||||
// TODO: configurable via graphics settings
|
||||
const Quality quality = Quality::Ultra;
|
||||
bool debugProbes = true; // TODO: add debug option to draw probes locations -> in Graphics window - Editor-only
|
||||
bool debugProbes = false; // TODO: add debug option to draw probes locations -> in Graphics window - Editor-only
|
||||
// TODO: configurable via postFx settings (maybe use Global SDF distance?)
|
||||
const float indirectLightingIntensity = 1.0f;
|
||||
const Vector3 giDistance(2000, 2000, 2000); // GI distance around the view (in each direction)
|
||||
@@ -291,7 +292,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
|
||||
const Int3 probesCounts(Vector3::Ceil(giDistance / giResolution));
|
||||
const Vector3 probesDistance = Vector3(probesCounts) * giResolution;
|
||||
const int32 probeRaysCount = Math::Min(Math::AlignUp(256, DDGI_TRACE_RAYS_GROUP_SIZE_X), DDGI_TRACE_RAYS_LIMIT); // TODO: make it based on the GI Quality
|
||||
const float probeHistoryWeight = 0.97f;
|
||||
const float probeHistoryWeight = 0.8f;
|
||||
|
||||
// Init buffers
|
||||
const int32 probesCount = probesCounts.X * probesCounts.Y * probesCounts.Z;
|
||||
@@ -347,6 +348,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
|
||||
viewOrigin += viewDirection * viewOriginOffset;
|
||||
const float viewOriginSnapping = giResolution;
|
||||
viewOrigin = Vector3::Floor(viewOrigin / viewOriginSnapping) * viewOriginSnapping;
|
||||
//viewOrigin = Vector3::Zero;
|
||||
CalculateVolumeScrolling(ddgiData, viewOrigin);
|
||||
|
||||
// Upload constants
|
||||
@@ -377,6 +379,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
|
||||
data.DDGI = ddgiData.Result.Constants;
|
||||
data.GlobalSDF = bindingDataSDF.Constants;
|
||||
data.GlobalSurfaceAtlas = bindingDataSurfaceAtlas.Constants;
|
||||
data.ResetBlend = clear ? 1.0f : 0.0f;
|
||||
data.IndirectLightingIntensity = indirectLightingIntensity;
|
||||
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
|
||||
context->UpdateCB(_cb0, &data);
|
||||
|
||||
@@ -437,7 +437,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
||||
surfaceAtlasData.TileTexelsPerWorldUnit = 1.0f / 10.0f; // Scales the tiles resolution
|
||||
surfaceAtlasData.DistanceScalingStart = 2000.0f; // Distance from camera at which the tiles resolution starts to be scaled down
|
||||
surfaceAtlasData.DistanceScalingEnd = 5000.0f; // Distance from camera at which the tiles resolution end to be scaled down
|
||||
surfaceAtlasData.DistanceScaling = 0.1f; // The scale for tiles at distanceScalingEnd and further away
|
||||
surfaceAtlasData.DistanceScaling = 0.2f; // The scale for tiles at distanceScalingEnd and further away
|
||||
// TODO: add DetailsScale param to adjust quality of scene details in Global Surface Atlas
|
||||
const uint32 viewMask = renderContext.View.RenderLayersMask;
|
||||
const Vector3 viewPosition = renderContext.View.Position;
|
||||
@@ -595,6 +595,9 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
||||
result.Constants.ChunkSize = distance / (float)GLOBAL_SURFACE_ATLAS_CHUNKS_RESOLUTION;
|
||||
result.Constants.ObjectsCount = surfaceAtlasData.Objects.Count();
|
||||
|
||||
// If we don't know the culled objects buffer capacity then we shouldn't use atlas results as many objects are still missing (see CulledObjectsCounterIndex usage)
|
||||
bool notReady = false;
|
||||
|
||||
// Cull objects into chunks (for faster Atlas sampling)
|
||||
if (surfaceAtlasData.Objects.Count() != 0)
|
||||
{
|
||||
@@ -620,18 +623,23 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
||||
if (surfaceAtlasData.CulledObjectsCounterIndex != -1)
|
||||
{
|
||||
// Get the last counter value (accept staging readback delay)
|
||||
notReady = true;
|
||||
auto data = (uint32*)_culledObjectsSizeBuffer->Map(GPUResourceMapMode::Read);
|
||||
if (data)
|
||||
{
|
||||
uint32 counter = data[surfaceAtlasData.CulledObjectsCounterIndex];
|
||||
_culledObjectsSizeBuffer->Unmap();
|
||||
if (counter > 0)
|
||||
{
|
||||
objectsBufferCapacity = counter * sizeof(Vector4);
|
||||
notReady = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (surfaceAtlasData.CulledObjectsCounterIndex == -1)
|
||||
{
|
||||
// Find a free timer slot
|
||||
notReady = true;
|
||||
for (int32 i = 0; i < ARRAY_COUNT(_culledObjectsSizeFrames); i++)
|
||||
{
|
||||
if (currentFrame - _culledObjectsSizeFrames[i] > GPU_ASYNC_LATENCY)
|
||||
@@ -870,12 +878,10 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
||||
context->ResetRenderTarget();
|
||||
}
|
||||
|
||||
// TODO: indirect lighting apply to get infinite bounces for GI
|
||||
|
||||
// TODO: explore atlas tiles optimization with feedback from renderer (eg. when tile is sampled by GI/Reflections mark it as used, then sort tiles by importance and prioritize updates for ones frequently used)
|
||||
|
||||
#undef WRITE_TILE
|
||||
return false;
|
||||
return notReady;
|
||||
}
|
||||
|
||||
void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContext* context, GPUTexture* output)
|
||||
|
||||
@@ -27,7 +27,8 @@ DDGIData DDGI;
|
||||
GlobalSDFData GlobalSDF;
|
||||
GlobalSurfaceAtlasData GlobalSurfaceAtlas;
|
||||
GBufferData GBuffer;
|
||||
float3 Padding0;
|
||||
float2 Padding0;
|
||||
float ResetBlend;
|
||||
float IndirectLightingIntensity;
|
||||
META_CB_END
|
||||
|
||||
@@ -228,8 +229,7 @@ void CS_UpdateProbes(uint3 DispatchThreadId : SV_DispatchThreadID, uint GroupInd
|
||||
{
|
||||
// Clear probe and return
|
||||
//RWOutput[outputCoords] = float4(0, 0, 0, 0);
|
||||
if (!skip)
|
||||
RWOutput[outputCoords] = float4(0, 0, 0, 0);
|
||||
//if (!skip) RWOutput[outputCoords] = float4(0, 0, 0, 0);
|
||||
skip = true;
|
||||
}
|
||||
}
|
||||
@@ -260,7 +260,7 @@ void CS_UpdateProbes(uint3 DispatchThreadId : SV_DispatchThreadID, uint GroupInd
|
||||
if (skip)
|
||||
{
|
||||
// Clear probe
|
||||
//RWOutput[outputCoords] = float4(0, 0, 0, 0);
|
||||
RWOutput[outputCoords] = float4(0, 0, 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -310,17 +310,15 @@ void CS_UpdateProbes(uint3 DispatchThreadId : SV_DispatchThreadID, uint GroupInd
|
||||
// Blend current value with the previous probe data
|
||||
float3 previous = RWOutput[outputCoords].rgb;
|
||||
float historyWeight = DDGI.ProbeHistoryWeight;
|
||||
if (dot(previous, previous) == 0)
|
||||
{
|
||||
// Cut any blend from zero
|
||||
//historyWeight = 0.0f;
|
||||
if (ResetBlend || dot(previous, previous) == 0)
|
||||
historyWeight = 0.0f;
|
||||
}
|
||||
#if DDGI_PROBE_UPDATE_MODE == 0
|
||||
result *= IndirectLightingIntensity;
|
||||
#if DDGI_SRGB_BLENDING
|
||||
result.rgb = pow(result.rgb, 1.0f / DDGI.IrradianceGamma);
|
||||
#endif
|
||||
float3 irradianceDelta = result.rgb - previous.rgb;
|
||||
float3 irradianceDelta = result.rgb - previous;
|
||||
float irradianceDeltaMax = Max3(abs(irradianceDelta));
|
||||
if (irradianceDeltaMax > 0.25f)
|
||||
{
|
||||
@@ -330,12 +328,13 @@ void CS_UpdateProbes(uint3 DispatchThreadId : SV_DispatchThreadID, uint GroupInd
|
||||
if (irradianceDeltaMax > 0.8f)
|
||||
{
|
||||
// Reduce flickering during rapid brightness changes
|
||||
result.rgb = previous.rgb + (irradianceDelta * 0.25f);
|
||||
result.rgb = previous + (irradianceDelta * 0.25f);
|
||||
}
|
||||
float3 resultDelta = (1.0f - historyWeight) * irradianceDelta;
|
||||
if (Max3(result.rgb) < Max3(previous.rgb))
|
||||
if (Max3(result.rgb) < Max3(previous))
|
||||
resultDelta = min(max(abs(resultDelta), 1.0f / 1024.0f), abs(irradianceDelta)) * sign(resultDelta);
|
||||
result = float4(previous.rgb + resultDelta, 1.0f);
|
||||
result = float4(previous + resultDelta, 1.0f);
|
||||
//result = float4(lerp(result.rgb, previous.rgb, historyWeight), 1.0f);
|
||||
#else
|
||||
result = float4(lerp(result.rg, previous.rg, historyWeight), 0.0f, 1.0f);
|
||||
#endif
|
||||
|
||||
@@ -117,6 +117,7 @@ float4 PS_Lighting(AtlasVertexOutput input) : SV_Target
|
||||
// Sample irradiance
|
||||
float bias = 1.0f;
|
||||
float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesState, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal, bias);
|
||||
//irradiance = 0;
|
||||
|
||||
// Calculate lighting
|
||||
float3 diffuseColor = GetDiffuseColor(gBuffer);
|
||||
|
||||
Reference in New Issue
Block a user