Refactor DDGI probes to use variable ray count depending on the probe location relative to the view frustum
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.
BIN
Content/Shaders/VolumetricFog.flax
(Stored with Git LFS)
BIN
Content/Shaders/VolumetricFog.flax
(Stored with Git LFS)
Binary file not shown.
@@ -170,7 +170,7 @@ bool GlobalIlluminationFeature::Bind(MaterialShader::BindParameters& params, Spa
|
|||||||
|
|
||||||
// Bind DDGI data
|
// Bind DDGI data
|
||||||
data.DDGI = bindingDataDDGI.Constants;
|
data.DDGI = bindingDataDDGI.Constants;
|
||||||
params.GPUContext->BindSR(srv + 0, bindingDataDDGI.ProbesState);
|
params.GPUContext->BindSR(srv + 0, bindingDataDDGI.ProbesData);
|
||||||
params.GPUContext->BindSR(srv + 1, bindingDataDDGI.ProbesDistance);
|
params.GPUContext->BindSR(srv + 1, bindingDataDDGI.ProbesDistance);
|
||||||
params.GPUContext->BindSR(srv + 2, bindingDataDDGI.ProbesIrradiance);
|
params.GPUContext->BindSR(srv + 2, bindingDataDDGI.ProbesIrradiance);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public:
|
|||||||
int32 ProbesCountTotal = 0;
|
int32 ProbesCountTotal = 0;
|
||||||
Int3 ProbeCounts = Int3::Zero;
|
Int3 ProbeCounts = Int3::Zero;
|
||||||
GPUTexture* ProbesTrace = nullptr; // Probes ray tracing: (RGB: hit radiance, A: hit distance)
|
GPUTexture* ProbesTrace = nullptr; // Probes ray tracing: (RGB: hit radiance, A: hit distance)
|
||||||
GPUTexture* ProbesState = nullptr; // Probes state: (RGB: world-space offset, A: state)
|
GPUTexture* ProbesData = nullptr; // Probes data: (RGB: world-space offset, A: state/data)
|
||||||
GPUTexture* ProbesIrradiance = nullptr; // Probes irradiance (RGB: sRGB color)
|
GPUTexture* ProbesIrradiance = nullptr; // Probes irradiance (RGB: sRGB color)
|
||||||
GPUTexture* ProbesDistance = nullptr; // Probes distance (R: mean distance, G: mean distance^2)
|
GPUTexture* ProbesDistance = nullptr; // Probes distance (R: mean distance, G: mean distance^2)
|
||||||
GPUBuffer* ActiveProbes = nullptr; // List with indices of the active probes (built during probes classification to use indirect dispatches for probes updating), counter at 0
|
GPUBuffer* ActiveProbes = nullptr; // List with indices of the active probes (built during probes classification to use indirect dispatches for probes updating), counter at 0
|
||||||
@@ -97,7 +97,7 @@ public:
|
|||||||
FORCE_INLINE void Release()
|
FORCE_INLINE void Release()
|
||||||
{
|
{
|
||||||
RenderTargetPool::Release(ProbesTrace);
|
RenderTargetPool::Release(ProbesTrace);
|
||||||
RenderTargetPool::Release(ProbesState);
|
RenderTargetPool::Release(ProbesData);
|
||||||
RenderTargetPool::Release(ProbesIrradiance);
|
RenderTargetPool::Release(ProbesIrradiance);
|
||||||
RenderTargetPool::Release(ProbesDistance);
|
RenderTargetPool::Release(ProbesDistance);
|
||||||
SAFE_DELETE_GPU_RESOURCE(ActiveProbes);
|
SAFE_DELETE_GPU_RESOURCE(ActiveProbes);
|
||||||
@@ -373,7 +373,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
|||||||
#define INIT_TEXTURE(texture, format, width, height) desc.Format = format; desc.Width = width; desc.Height = height; ddgiData.texture = RenderTargetPool::Get(desc); if (!ddgiData.texture) return true; memUsage += ddgiData.texture->GetMemoryUsage(); RENDER_TARGET_POOL_SET_NAME(ddgiData.texture, "DDGI." #texture)
|
#define INIT_TEXTURE(texture, format, width, height) desc.Format = format; desc.Width = width; desc.Height = height; ddgiData.texture = RenderTargetPool::Get(desc); if (!ddgiData.texture) return true; memUsage += ddgiData.texture->GetMemoryUsage(); RENDER_TARGET_POOL_SET_NAME(ddgiData.texture, "DDGI." #texture)
|
||||||
desc.Flags = GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess;
|
desc.Flags = GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess;
|
||||||
INIT_TEXTURE(ProbesTrace, PixelFormat::R16G16B16A16_Float, probeRaysCount, Math::Min(probesCountCascade, DDGI_TRACE_RAYS_PROBES_COUNT_LIMIT));
|
INIT_TEXTURE(ProbesTrace, PixelFormat::R16G16B16A16_Float, probeRaysCount, Math::Min(probesCountCascade, DDGI_TRACE_RAYS_PROBES_COUNT_LIMIT));
|
||||||
INIT_TEXTURE(ProbesState, PixelFormat::R8G8B8A8_SNorm, probesCountTotalX, probesCountTotalY);
|
INIT_TEXTURE(ProbesData, PixelFormat::R8G8B8A8_SNorm, probesCountTotalX, probesCountTotalY);
|
||||||
INIT_TEXTURE(ProbesIrradiance, PixelFormat::R11G11B10_Float, probesCountTotalX * (DDGI_PROBE_RESOLUTION_IRRADIANCE + 2), probesCountTotalY * (DDGI_PROBE_RESOLUTION_IRRADIANCE + 2));
|
INIT_TEXTURE(ProbesIrradiance, PixelFormat::R11G11B10_Float, probesCountTotalX * (DDGI_PROBE_RESOLUTION_IRRADIANCE + 2), probesCountTotalY * (DDGI_PROBE_RESOLUTION_IRRADIANCE + 2));
|
||||||
INIT_TEXTURE(ProbesDistance, PixelFormat::R16G16_Float, probesCountTotalX * (DDGI_PROBE_RESOLUTION_DISTANCE + 2), probesCountTotalY * (DDGI_PROBE_RESOLUTION_DISTANCE + 2));
|
INIT_TEXTURE(ProbesDistance, PixelFormat::R16G16_Float, probesCountTotalX * (DDGI_PROBE_RESOLUTION_DISTANCE + 2), probesCountTotalY * (DDGI_PROBE_RESOLUTION_DISTANCE + 2));
|
||||||
#undef INIT_TEXTURE
|
#undef INIT_TEXTURE
|
||||||
@@ -393,7 +393,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
|||||||
{
|
{
|
||||||
// Clear probes
|
// Clear probes
|
||||||
PROFILE_GPU("Clear");
|
PROFILE_GPU("Clear");
|
||||||
context->ClearUA(ddgiData.ProbesState, Float4::Zero);
|
context->ClearUA(ddgiData.ProbesData, Float4::Zero);
|
||||||
context->ClearUA(ddgiData.ProbesIrradiance, Float4::Zero);
|
context->ClearUA(ddgiData.ProbesIrradiance, Float4::Zero);
|
||||||
context->ClearUA(ddgiData.ProbesDistance, Float4::Zero);
|
context->ClearUA(ddgiData.ProbesDistance, Float4::Zero);
|
||||||
}
|
}
|
||||||
@@ -458,7 +458,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
|||||||
ddgiData.Result.Constants.IrradianceGamma = 1.5f;
|
ddgiData.Result.Constants.IrradianceGamma = 1.5f;
|
||||||
ddgiData.Result.Constants.IndirectLightingIntensity = indirectLightingIntensity;
|
ddgiData.Result.Constants.IndirectLightingIntensity = indirectLightingIntensity;
|
||||||
ddgiData.Result.Constants.FallbackIrradiance = fallbackIrradiance.ToFloat3() * fallbackIrradiance.A;
|
ddgiData.Result.Constants.FallbackIrradiance = fallbackIrradiance.ToFloat3() * fallbackIrradiance.A;
|
||||||
ddgiData.Result.ProbesState = ddgiData.ProbesState->View();
|
ddgiData.Result.ProbesData = ddgiData.ProbesData->View();
|
||||||
ddgiData.Result.ProbesDistance = ddgiData.ProbesDistance->View();
|
ddgiData.Result.ProbesDistance = ddgiData.ProbesDistance->View();
|
||||||
ddgiData.Result.ProbesIrradiance = ddgiData.ProbesIrradiance->View();
|
ddgiData.Result.ProbesIrradiance = ddgiData.ProbesIrradiance->View();
|
||||||
|
|
||||||
@@ -516,7 +516,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
|||||||
threadGroupsX = Math::DivideAndRoundUp(probesCountCascade, DDGI_PROBE_CLASSIFY_GROUP_SIZE);
|
threadGroupsX = Math::DivideAndRoundUp(probesCountCascade, DDGI_PROBE_CLASSIFY_GROUP_SIZE);
|
||||||
context->BindSR(0, bindingDataSDF.Texture ? bindingDataSDF.Texture->ViewVolume() : nullptr);
|
context->BindSR(0, bindingDataSDF.Texture ? bindingDataSDF.Texture->ViewVolume() : nullptr);
|
||||||
context->BindSR(1, bindingDataSDF.TextureMip ? bindingDataSDF.TextureMip->ViewVolume() : nullptr);
|
context->BindSR(1, bindingDataSDF.TextureMip ? bindingDataSDF.TextureMip->ViewVolume() : nullptr);
|
||||||
context->BindUA(0, ddgiData.Result.ProbesState);
|
context->BindUA(0, ddgiData.Result.ProbesData);
|
||||||
context->BindUA(1, ddgiData.ActiveProbes->View());
|
context->BindUA(1, ddgiData.ActiveProbes->View());
|
||||||
Data1 data;
|
Data1 data;
|
||||||
data.CascadeIndex = cascadeIndex;
|
data.CascadeIndex = cascadeIndex;
|
||||||
@@ -558,7 +558,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
|||||||
context->BindSR(4, bindingDataSurfaceAtlas.Objects ? bindingDataSurfaceAtlas.Objects->View() : nullptr);
|
context->BindSR(4, bindingDataSurfaceAtlas.Objects ? bindingDataSurfaceAtlas.Objects->View() : nullptr);
|
||||||
context->BindSR(5, bindingDataSurfaceAtlas.AtlasDepth->View());
|
context->BindSR(5, bindingDataSurfaceAtlas.AtlasDepth->View());
|
||||||
context->BindSR(6, bindingDataSurfaceAtlas.AtlasLighting->View());
|
context->BindSR(6, bindingDataSurfaceAtlas.AtlasLighting->View());
|
||||||
context->BindSR(7, ddgiData.Result.ProbesState);
|
context->BindSR(7, ddgiData.Result.ProbesData);
|
||||||
context->BindSR(8, skybox);
|
context->BindSR(8, skybox);
|
||||||
context->BindSR(9, ddgiData.ActiveProbes->View());
|
context->BindSR(9, ddgiData.ActiveProbes->View());
|
||||||
context->BindUA(0, ddgiData.ProbesTrace->View());
|
context->BindUA(0, ddgiData.ProbesTrace->View());
|
||||||
@@ -570,7 +570,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
|||||||
// Update probes irradiance and distance textures (one thread-group per probe)
|
// Update probes irradiance and distance textures (one thread-group per probe)
|
||||||
{
|
{
|
||||||
PROFILE_GPU_CPU_NAMED("Update Probes");
|
PROFILE_GPU_CPU_NAMED("Update Probes");
|
||||||
context->BindSR(0, ddgiData.Result.ProbesState);
|
context->BindSR(0, ddgiData.Result.ProbesData);
|
||||||
context->BindSR(1, ddgiData.ProbesTrace->View());
|
context->BindSR(1, ddgiData.ProbesTrace->View());
|
||||||
context->BindSR(2, ddgiData.ActiveProbes->View());
|
context->BindSR(2, ddgiData.ActiveProbes->View());
|
||||||
context->BindUA(0, ddgiData.Result.ProbesIrradiance);
|
context->BindUA(0, ddgiData.Result.ProbesIrradiance);
|
||||||
@@ -682,7 +682,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
|
|||||||
context->BindSR(1, renderContext.Buffers->GBuffer1->View());
|
context->BindSR(1, renderContext.Buffers->GBuffer1->View());
|
||||||
context->BindSR(2, renderContext.Buffers->GBuffer2->View());
|
context->BindSR(2, renderContext.Buffers->GBuffer2->View());
|
||||||
context->BindSR(3, renderContext.Buffers->DepthBuffer->View());
|
context->BindSR(3, renderContext.Buffers->DepthBuffer->View());
|
||||||
context->BindSR(4, ddgiData.Result.ProbesState);
|
context->BindSR(4, ddgiData.Result.ProbesData);
|
||||||
context->BindSR(5, ddgiData.Result.ProbesDistance);
|
context->BindSR(5, ddgiData.Result.ProbesDistance);
|
||||||
context->BindSR(6, ddgiData.Result.ProbesIrradiance);
|
context->BindSR(6, ddgiData.Result.ProbesIrradiance);
|
||||||
context->SetViewportAndScissors(renderContext.View.ScreenSize.X, renderContext.View.ScreenSize.Y);
|
context->SetViewportAndScissors(renderContext.View.ScreenSize.X, renderContext.View.ScreenSize.Y);
|
||||||
@@ -724,7 +724,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
|
|||||||
context->SetRenderTarget(*renderContext.Buffers->DepthBuffer, ToSpan(targetBuffers, ARRAY_COUNT(targetBuffers)));
|
context->SetRenderTarget(*renderContext.Buffers->DepthBuffer, ToSpan(targetBuffers, ARRAY_COUNT(targetBuffers)));
|
||||||
{
|
{
|
||||||
// Pass DDGI data to the material
|
// Pass DDGI data to the material
|
||||||
_debugMaterial->SetParameterValue(TEXT("ProbesState"), Variant(ddgiData.ProbesState));
|
_debugMaterial->SetParameterValue(TEXT("ProbesData"), Variant(ddgiData.ProbesData));
|
||||||
_debugMaterial->SetParameterValue(TEXT("ProbesIrradiance"), Variant(ddgiData.ProbesIrradiance));
|
_debugMaterial->SetParameterValue(TEXT("ProbesIrradiance"), Variant(ddgiData.ProbesIrradiance));
|
||||||
_debugMaterial->SetParameterValue(TEXT("ProbesDistance"), Variant(ddgiData.ProbesDistance));
|
_debugMaterial->SetParameterValue(TEXT("ProbesDistance"), Variant(ddgiData.ProbesDistance));
|
||||||
auto cb = _debugMaterial->GetShader()->GetCB(3);
|
auto cb = _debugMaterial->GetShader()->GetCB(3);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public:
|
|||||||
struct BindingData
|
struct BindingData
|
||||||
{
|
{
|
||||||
ConstantsData Constants;
|
ConstantsData Constants;
|
||||||
GPUTextureView* ProbesState;
|
GPUTextureView* ProbesData;
|
||||||
GPUTextureView* ProbesDistance;
|
GPUTextureView* ProbesDistance;
|
||||||
GPUTextureView* ProbesIrradiance;
|
GPUTextureView* ProbesIrradiance;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1056,7 +1056,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co
|
|||||||
PROFILE_GPU_CPU_NAMED("DDGI");
|
PROFILE_GPU_CPU_NAMED("DDGI");
|
||||||
data.DDGI = bindingDataDDGI.Constants;
|
data.DDGI = bindingDataDDGI.Constants;
|
||||||
data.Light.Radius = giSettings.BounceIntensity / bindingDataDDGI.Constants.IndirectLightingIntensity; // Reuse for smaller CB
|
data.Light.Radius = giSettings.BounceIntensity / bindingDataDDGI.Constants.IndirectLightingIntensity; // Reuse for smaller CB
|
||||||
context->BindSR(5, bindingDataDDGI.ProbesState);
|
context->BindSR(5, bindingDataDDGI.ProbesData);
|
||||||
context->BindSR(6, bindingDataDDGI.ProbesDistance);
|
context->BindSR(6, bindingDataDDGI.ProbesDistance);
|
||||||
context->BindSR(7, bindingDataDDGI.ProbesIrradiance);
|
context->BindSR(7, bindingDataDDGI.ProbesIrradiance);
|
||||||
context->UpdateCB(_cb0, &data);
|
context->UpdateCB(_cb0, &data);
|
||||||
|
|||||||
@@ -671,7 +671,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext)
|
|||||||
int32 csIndex;
|
int32 csIndex;
|
||||||
if (useDDGI)
|
if (useDDGI)
|
||||||
{
|
{
|
||||||
context->BindSR(5, bindingDataDDGI.ProbesState);
|
context->BindSR(5, bindingDataDDGI.ProbesData);
|
||||||
context->BindSR(6, bindingDataDDGI.ProbesDistance);
|
context->BindSR(6, bindingDataDDGI.ProbesDistance);
|
||||||
context->BindSR(7, bindingDataDDGI.ProbesIrradiance);
|
context->BindSR(7, bindingDataDDGI.ProbesIrradiance);
|
||||||
csIndex = 1;
|
csIndex = 1;
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
#include "./Flax/Math.hlsl"
|
#include "./Flax/Math.hlsl"
|
||||||
#include "./Flax/Octahedral.hlsl"
|
#include "./Flax/Octahedral.hlsl"
|
||||||
|
|
||||||
#define DDGI_PROBE_STATE_INACTIVE 0.0f
|
#define DDGI_PROBE_STATE_INACTIVE 0
|
||||||
#define DDGI_PROBE_STATE_ACTIVATED 0.2f
|
#define DDGI_PROBE_STATE_ACTIVATED 1
|
||||||
#define DDGI_PROBE_STATE_ACTIVE 1.0f
|
#define DDGI_PROBE_STATE_ACTIVE 2
|
||||||
#define DDGI_PROBE_RESOLUTION_IRRADIANCE 6 // Resolution (in texels) for probe irradiance data (excluding 1px padding on each side)
|
#define DDGI_PROBE_RESOLUTION_IRRADIANCE 6 // Resolution (in texels) for probe irradiance data (excluding 1px padding on each side)
|
||||||
#define DDGI_PROBE_RESOLUTION_DISTANCE 14 // Resolution (in texels) for probe distance data (excluding 1px padding on each side)
|
#define DDGI_PROBE_RESOLUTION_DISTANCE 14 // Resolution (in texels) for probe distance data (excluding 1px padding on each side)
|
||||||
#define DDGI_SRGB_BLENDING 1 // Enables blending in sRGB color space, otherwise irradiance blending is done in linear space
|
#define DDGI_SRGB_BLENDING 1 // Enables blending in sRGB color space, otherwise irradiance blending is done in linear space
|
||||||
@@ -89,22 +89,32 @@ float3 GetDDGIProbeWorldPosition(DDGIData data, uint cascadeIndex, uint3 probeCo
|
|||||||
return probesOrigin + probePosition - probeGridOffset + (data.ProbesScrollOffsets[cascadeIndex].xyz * probesSpacing);
|
return probesOrigin + probePosition - probeGridOffset + (data.ProbesScrollOffsets[cascadeIndex].xyz * probesSpacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads probe probe state
|
// Loads probe probe data (encoded)
|
||||||
float LoadDDGIProbeState(DDGIData data, Texture2D<snorm float4> probesState, uint cascadeIndex, uint probeIndex)
|
float4 LoadDDGIProbeData(DDGIData data, Texture2D<snorm float4> probesData, uint cascadeIndex, uint probeIndex)
|
||||||
{
|
{
|
||||||
int2 probeDataCoords = GetDDGIProbeTexelCoords(data, cascadeIndex, probeIndex);
|
int2 probeDataCoords = GetDDGIProbeTexelCoords(data, cascadeIndex, probeIndex);
|
||||||
float4 probeState = probesState.Load(int3(probeDataCoords, 0));
|
return probesData.Load(int3(probeDataCoords, 0));
|
||||||
return probeState.w;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loads probe world-space position (XYZ) and probe state (W)
|
// Encodes probe probe data
|
||||||
float4 LoadDDGIProbePositionAndState(DDGIData data, Texture2D<snorm float4> probesState, uint cascadeIndex, uint probeIndex, uint3 probeCoords)
|
float4 EncodeDDGIProbeData(float3 probeOffset, uint probeState)
|
||||||
{
|
{
|
||||||
int2 probeDataCoords = GetDDGIProbeTexelCoords(data, cascadeIndex, probeIndex);
|
return float4(probeOffset, (float)probeState * (1.0f / 8.0f));
|
||||||
float4 probeState = probesState.Load(int3(probeDataCoords, 0));
|
}
|
||||||
probeState.xyz *= data.ProbesOriginAndSpacing[cascadeIndex].w; // Probe offset is [-1;1] within probes spacing
|
|
||||||
probeState.xyz += GetDDGIProbeWorldPosition(data, cascadeIndex, probeCoords); // Place probe on a grid
|
// Decodes probe state from the encoded state
|
||||||
return probeState;
|
uint DecodeDDGIProbeState(float4 probeData)
|
||||||
|
{
|
||||||
|
return (uint)(probeData.w * 8.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decodes probe world-space position (XYZ) from the encoded state
|
||||||
|
float3 DecodeDDGIProbePosition(DDGIData data, float4 probeData, uint cascadeIndex, uint probeIndex, uint3 probeCoords)
|
||||||
|
{
|
||||||
|
float3 probePosition = probeData.xyz;
|
||||||
|
probePosition *= data.ProbesOriginAndSpacing[cascadeIndex].w; // Probe offset is [-1;1] within probes spacing
|
||||||
|
probePosition += GetDDGIProbeWorldPosition(data, cascadeIndex, probeCoords); // Place probe on a grid
|
||||||
|
return probePosition;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates texture UVs for sampling probes atlas texture (irradiance or distance)
|
// Calculates texture UVs for sampling probes atlas texture (irradiance or distance)
|
||||||
@@ -122,11 +132,11 @@ float2 GetDDGIProbeUV(DDGIData data, uint cascadeIndex, uint probeIndex, float2
|
|||||||
// Samples DDGI probes volume at the given world-space position and returns the irradiance.
|
// Samples DDGI probes volume at the given world-space position and returns the irradiance.
|
||||||
// bias - scales the bias vector to the initial sample point to reduce self-shading artifacts
|
// 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
|
// dither - randomized per-pixel value in range 0-1, used to smooth dithering for cascades blending
|
||||||
float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesState, Texture2D<float4> probesDistance, Texture2D<float4> probesIrradiance, float3 worldPosition, float3 worldNormal, float bias = 0.2f, float dither = 0.0f)
|
float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesData, Texture2D<float4> probesDistance, Texture2D<float4> probesIrradiance, float3 worldPosition, float3 worldNormal, float bias = 0.2f, float dither = 0.0f)
|
||||||
{
|
{
|
||||||
// Select the highest cascade that contains the sample location
|
// Select the highest cascade that contains the sample location
|
||||||
uint cascadeIndex = 0;
|
uint cascadeIndex = 0;
|
||||||
float4 probeStates[8];
|
float4 probesDatas[8];
|
||||||
for (; cascadeIndex < data.CascadesCount; cascadeIndex++)
|
for (; cascadeIndex < data.CascadesCount; cascadeIndex++)
|
||||||
{
|
{
|
||||||
float probesSpacing = data.ProbesOriginAndSpacing[cascadeIndex].w;
|
float probesSpacing = data.ProbesOriginAndSpacing[cascadeIndex].w;
|
||||||
@@ -145,9 +155,10 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesState,
|
|||||||
uint3 probeCoordsOffset = uint3(i, i >> 1, i >> 2) & 1;
|
uint3 probeCoordsOffset = uint3(i, i >> 1, i >> 2) & 1;
|
||||||
uint3 probeCoords = clamp(baseProbeCoords + probeCoordsOffset, uint3(0, 0, 0), data.ProbesCounts - uint3(1, 1, 1));
|
uint3 probeCoords = clamp(baseProbeCoords + probeCoordsOffset, uint3(0, 0, 0), data.ProbesCounts - uint3(1, 1, 1));
|
||||||
uint probeIndex = GetDDGIScrollingProbeIndex(data, cascadeIndex, probeCoords);
|
uint probeIndex = GetDDGIScrollingProbeIndex(data, cascadeIndex, probeCoords);
|
||||||
float4 probeState = probesState.Load(int3(GetDDGIProbeTexelCoords(data, cascadeIndex, probeIndex), 0));
|
float4 probeData = LoadDDGIProbeData(data, probesData, cascadeIndex, probeIndex);
|
||||||
probeStates[i] = probeState;
|
probesDatas[i] = probeData;
|
||||||
if (probeState.w != DDGI_PROBE_STATE_INACTIVE)
|
uint probeState = DecodeDDGIProbeState(probeData);
|
||||||
|
if (probeState != DDGI_PROBE_STATE_INACTIVE)
|
||||||
activeCount++;
|
activeCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,12 +193,12 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesState,
|
|||||||
uint probeIndex = GetDDGIScrollingProbeIndex(data, cascadeIndex, probeCoords);
|
uint probeIndex = GetDDGIScrollingProbeIndex(data, cascadeIndex, probeCoords);
|
||||||
|
|
||||||
// Load probe position and state
|
// Load probe position and state
|
||||||
float4 probeState = probeStates[i];
|
float4 probeData = probesDatas[i];
|
||||||
if (probeState.w == DDGI_PROBE_STATE_INACTIVE)
|
uint probeState = DecodeDDGIProbeState(probeData);
|
||||||
|
if (probeState == DDGI_PROBE_STATE_INACTIVE)
|
||||||
continue;
|
continue;
|
||||||
probeState.xyz *= probesSpacing; // Probe offset is [-1;1] within probes spacing
|
|
||||||
float3 probeBasePosition = baseProbeWorldPosition + ((probeCoords - baseProbeCoords) * probesSpacing);
|
float3 probeBasePosition = baseProbeWorldPosition + ((probeCoords - baseProbeCoords) * probesSpacing);
|
||||||
float3 probePosition = probeBasePosition + probeState.xyz;
|
float3 probePosition = probeBasePosition + probeData.xyz * probesSpacing; // Probe offset is [-1;1] within probes spacing
|
||||||
|
|
||||||
// Calculate the distance and direction from the (biased and non-biased) shading point and the probe
|
// Calculate the distance and direction from the (biased and non-biased) shading point and the probe
|
||||||
float3 worldPosToProbe = normalize(probePosition - worldPosition);
|
float3 worldPosToProbe = normalize(probePosition - worldPosition);
|
||||||
@@ -233,7 +244,7 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesState,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Debug probe offset visualization
|
// Debug probe offset visualization
|
||||||
//probeIrradiance = float3(max(frac(probeState.xyz) * 2, 0.1f));
|
//probeIrradiance = float3(max(frac(probeData.xyz) * 2, 0.1f));
|
||||||
|
|
||||||
// Accumulate weighted irradiance
|
// Accumulate weighted irradiance
|
||||||
irradiance += float4(probeIrradiance * weight, weight);
|
irradiance += float4(probeIrradiance * weight, weight);
|
||||||
|
|||||||
@@ -58,17 +58,18 @@ float3 GetProbeRayDirection(DDGIData data, uint rayIndex)
|
|||||||
return normalize(QuaternionRotate(data.RaysRotation, direction));
|
return normalize(QuaternionRotate(data.RaysRotation, direction));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if the probe states are equal
|
// Calculates amount of rays to allocate for a probe
|
||||||
bool GetProbeState(float a, float b)
|
uint GetProbeRaysCount(DDGIData data, uint probeState)
|
||||||
{
|
{
|
||||||
return abs(a - b) < 0.05f;
|
// TODO: implement variable ray count based on probe location relative to the view frustum (use probe state for storage)
|
||||||
|
return data.RaysCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _CS_Classify
|
#ifdef _CS_Classify
|
||||||
|
|
||||||
#define DDGI_PROBE_RELOCATE_ITERATIVE 0 // If true, probes relocation algorithm tries to move them in additive way, otherwise all nearby locations are checked to find the best position
|
#define DDGI_PROBE_RELOCATE_ITERATIVE 0 // If true, probes relocation algorithm tries to move them in additive way, otherwise all nearby locations are checked to find the best position
|
||||||
|
|
||||||
RWTexture2D<snorm float4> RWProbesState : register(u0);
|
RWTexture2D<snorm float4> RWProbesData : register(u0);
|
||||||
RWByteAddressBuffer RWActiveProbes : register(u1);
|
RWByteAddressBuffer RWActiveProbes : register(u1);
|
||||||
|
|
||||||
Texture3D<float> GlobalSDFTex : register(t0);
|
Texture3D<float> GlobalSDFTex : register(t0);
|
||||||
@@ -79,7 +80,7 @@ float3 Remap(float3 value, float3 fromMin, float3 fromMax, float3 toMin, float3
|
|||||||
return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin;
|
return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute shader for updating probes state between active and inactive.
|
// Compute shader for updating probes state between active and inactive and performing probes relocation.
|
||||||
META_CS(true, FEATURE_LEVEL_SM5)
|
META_CS(true, FEATURE_LEVEL_SM5)
|
||||||
[numthreads(DDGI_PROBE_CLASSIFY_GROUP_SIZE, 1, 1)]
|
[numthreads(DDGI_PROBE_CLASSIFY_GROUP_SIZE, 1, 1)]
|
||||||
void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
||||||
@@ -94,14 +95,15 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
|||||||
float probesSpacing = DDGI.ProbesOriginAndSpacing[CascadeIndex].w;
|
float probesSpacing = DDGI.ProbesOriginAndSpacing[CascadeIndex].w;
|
||||||
|
|
||||||
// Load probe state and position
|
// Load probe state and position
|
||||||
float4 probeState = RWProbesState[probeDataCoords];
|
float4 probeData = RWProbesData[probeDataCoords];
|
||||||
probeState.xyz *= probesSpacing; // Probe offset is [-1;1] within probes spacing
|
uint probeState = DecodeDDGIProbeState(probeData);
|
||||||
|
float3 probeOffset = probeData.xyz * probesSpacing; // Probe offset is [-1;1] within probes spacing
|
||||||
|
float3 probeOffsetOld = probeOffset;
|
||||||
float3 probeBasePosition = GetDDGIProbeWorldPosition(DDGI, CascadeIndex, probeCoords);
|
float3 probeBasePosition = GetDDGIProbeWorldPosition(DDGI, CascadeIndex, probeCoords);
|
||||||
float3 probePosition = probeBasePosition;
|
float3 probePosition = probeBasePosition;
|
||||||
#if DDGI_PROBE_RELOCATE_ITERATIVE
|
#if DDGI_PROBE_RELOCATE_ITERATIVE
|
||||||
probePosition += probeState.xyz;
|
probePosition += probeOffset;
|
||||||
#endif
|
#endif
|
||||||
float4 probeStateOld = probeState;
|
|
||||||
|
|
||||||
// Use Global SDF to quickly get distance and direction to the scene geometry
|
// Use Global SDF to quickly get distance and direction to the scene geometry
|
||||||
#if DDGI_PROBE_RELOCATE_ITERATIVE
|
#if DDGI_PROBE_RELOCATE_ITERATIVE
|
||||||
@@ -117,7 +119,8 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
|||||||
if (sdfDst > distanceLimit) // Probe is too far from geometry
|
if (sdfDst > distanceLimit) // Probe is too far from geometry
|
||||||
{
|
{
|
||||||
// Disable it
|
// Disable it
|
||||||
probeState = float4(0, 0, 0, DDGI_PROBE_STATE_INACTIVE);
|
probeOffset = float3(0, 0, 0);
|
||||||
|
probeState = DDGI_PROBE_STATE_INACTIVE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -127,22 +130,22 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
|||||||
if (sdfDst < relocateLimit)
|
if (sdfDst < relocateLimit)
|
||||||
{
|
{
|
||||||
float3 offsetToAdd = sdfNormal * (sdf + threshold);
|
float3 offsetToAdd = sdfNormal * (sdf + threshold);
|
||||||
if (distance(probeState.xyz, offsetToAdd) < relocateLimit)
|
if (distance(probeOffset, offsetToAdd) < relocateLimit)
|
||||||
{
|
{
|
||||||
// Relocate it
|
// Relocate it
|
||||||
probeState.xyz += offsetToAdd;
|
probeOffset += offsetToAdd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Reset relocation
|
// Reset relocation
|
||||||
probeState.xyz = float3(0, 0, 0);
|
probeOffset = float3(0, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sdf > threshold * 4.0f) // Probe is far enough from any geometry
|
else if (sdf > threshold * 4.0f) // Probe is far enough from any geometry
|
||||||
{
|
{
|
||||||
// Reset relocation
|
// Reset relocation
|
||||||
probeState.xyz = float3(0, 0, 0);
|
probeOffset = float3(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if probe is relocated but the base location is fine
|
// Check if probe is relocated but the base location is fine
|
||||||
@@ -150,7 +153,7 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
|||||||
if (sdf > threshold)
|
if (sdf > threshold)
|
||||||
{
|
{
|
||||||
// Reset relocation
|
// Reset relocation
|
||||||
probeState.xyz = float3(0, 0, 0);
|
probeOffset = float3(0, 0, 0);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
// Sample Global SDF around the probe location
|
// Sample Global SDF around the probe location
|
||||||
@@ -177,7 +180,7 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
|||||||
// Relocate the probe to the best found location (or zero if nothing good found)
|
// Relocate the probe to the best found location (or zero if nothing good found)
|
||||||
if (bestOffset.w <= threshold)
|
if (bestOffset.w <= threshold)
|
||||||
bestOffset.xyz = float3(0, 0, 0);
|
bestOffset.xyz = float3(0, 0, 0);
|
||||||
probeState.xyz = bestOffset.xyz;
|
probeOffset = bestOffset.xyz;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Check if probe was scrolled
|
// Check if probe was scrolled
|
||||||
@@ -189,23 +192,21 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
|||||||
int probeCount = (int)DDGI.ProbesCounts[planeIndex];
|
int probeCount = (int)DDGI.ProbesCounts[planeIndex];
|
||||||
int newCord = (int)probeCoords[planeIndex] + probeScrollClears[planeIndex];
|
int newCord = (int)probeCoords[planeIndex] + probeScrollClears[planeIndex];
|
||||||
if (newCord < 0 || newCord >= probeCount)
|
if (newCord < 0 || newCord >= probeCount)
|
||||||
{
|
|
||||||
wasScrolled = true;
|
wasScrolled = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If probe was in different location or was inactive last frame then mark it as activated
|
// If probe was in different location or was inactive last frame then mark it as activated
|
||||||
bool wasInactive = probeStateOld.w == DDGI_PROBE_STATE_INACTIVE;
|
bool wasInactive = probeState == DDGI_PROBE_STATE_INACTIVE;
|
||||||
bool wasRelocated = distance(probeState.xyz, probeStateOld.xyz) > 2.0f;
|
bool wasRelocated = distance(probeOffset, probeOffsetOld) > 2.0f;
|
||||||
probeState.w = wasInactive || wasScrolled || wasRelocated ? DDGI_PROBE_STATE_ACTIVATED : DDGI_PROBE_STATE_ACTIVE;
|
probeState = wasInactive || wasScrolled || wasRelocated ? DDGI_PROBE_STATE_ACTIVATED : DDGI_PROBE_STATE_ACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save probe state
|
// Save probe state
|
||||||
probeState.xyz /= probesSpacing;
|
probeOffset /= probesSpacing; // Move offset back to [-1;1] space
|
||||||
RWProbesState[probeDataCoords] = probeState;
|
RWProbesData[probeDataCoords] = EncodeDDGIProbeData(probeOffset, probeState);
|
||||||
|
|
||||||
// Collect active probes
|
// Collect active probes
|
||||||
if (probeState.w != DDGI_PROBE_STATE_INACTIVE)
|
if (probeState != DDGI_PROBE_STATE_INACTIVE)
|
||||||
{
|
{
|
||||||
uint activeProbeIndex;
|
uint activeProbeIndex;
|
||||||
RWActiveProbes.InterlockedAdd(0, 1, activeProbeIndex); // Counter at 0
|
RWActiveProbes.InterlockedAdd(0, 1, activeProbeIndex); // Counter at 0
|
||||||
@@ -250,7 +251,7 @@ ByteAddressBuffer RWGlobalSurfaceAtlasCulledObjects : register(t3);
|
|||||||
Buffer<float4> GlobalSurfaceAtlasObjects : register(t4);
|
Buffer<float4> GlobalSurfaceAtlasObjects : register(t4);
|
||||||
Texture2D GlobalSurfaceAtlasDepth : register(t5);
|
Texture2D GlobalSurfaceAtlasDepth : register(t5);
|
||||||
Texture2D GlobalSurfaceAtlasTex : register(t6);
|
Texture2D GlobalSurfaceAtlasTex : register(t6);
|
||||||
Texture2D<snorm float4> ProbesState : register(t7);
|
Texture2D<snorm float4> ProbesData : register(t7);
|
||||||
TextureCube Skybox : register(t8);
|
TextureCube Skybox : register(t8);
|
||||||
ByteAddressBuffer ActiveProbes : register(t9);
|
ByteAddressBuffer ActiveProbes : register(t9);
|
||||||
|
|
||||||
@@ -269,14 +270,17 @@ void CS_TraceRays(uint3 DispatchThreadId : SV_DispatchThreadID)
|
|||||||
probeIndex = GetDDGIScrollingProbeIndex(DDGI, CascadeIndex, probeCoords);
|
probeIndex = GetDDGIScrollingProbeIndex(DDGI, CascadeIndex, probeCoords);
|
||||||
|
|
||||||
// Load current probe state and position
|
// Load current probe state and position
|
||||||
float4 probePositionAndState = LoadDDGIProbePositionAndState(DDGI, ProbesState, CascadeIndex, probeIndex, probeCoords);
|
float4 probeData = LoadDDGIProbeData(DDGI, ProbesData, CascadeIndex, probeIndex);
|
||||||
if (probePositionAndState.w == DDGI_PROBE_STATE_INACTIVE)
|
uint probeState = DecodeDDGIProbeState(probeData);
|
||||||
return; // Skip disabled probes
|
uint probeRaysCount = GetProbeRaysCount(DDGI, probeState);
|
||||||
|
if (probeState == DDGI_PROBE_STATE_INACTIVE || probeRaysCount < rayIndex)
|
||||||
|
return; // Skip disabled probes or if current thread's ray is unused
|
||||||
|
float3 probePosition = DecodeDDGIProbePosition(DDGI, probeData, CascadeIndex, probeIndex, probeCoords);
|
||||||
float3 probeRayDirection = GetProbeRayDirection(DDGI, rayIndex);
|
float3 probeRayDirection = GetProbeRayDirection(DDGI, rayIndex);
|
||||||
|
|
||||||
// Trace ray with Global SDF
|
// Trace ray with Global SDF
|
||||||
GlobalSDFTrace trace;
|
GlobalSDFTrace trace;
|
||||||
trace.Init(probePositionAndState.xyz, probeRayDirection, 0.0f, DDGI.RayMaxDistance);
|
trace.Init(probePosition, probeRayDirection, 0.0f, DDGI.RayMaxDistance);
|
||||||
GlobalSDFHit hit = RayTraceGlobalSDF(GlobalSDF, GlobalSDFTex, GlobalSDFMip, trace);
|
GlobalSDFHit hit = RayTraceGlobalSDF(GlobalSDF, GlobalSDFTex, GlobalSDFMip, trace);
|
||||||
|
|
||||||
// Calculate radiance and distance
|
// Calculate radiance and distance
|
||||||
@@ -328,7 +332,7 @@ groupshared float CachedProbesTraceDistance[DDGI_TRACE_RAYS_LIMIT];
|
|||||||
groupshared float3 CachedProbesTraceDirection[DDGI_TRACE_RAYS_LIMIT];
|
groupshared float3 CachedProbesTraceDirection[DDGI_TRACE_RAYS_LIMIT];
|
||||||
|
|
||||||
RWTexture2D<float4> RWOutput : register(u0);
|
RWTexture2D<float4> RWOutput : register(u0);
|
||||||
Texture2D<snorm float4> ProbesState : register(t0);
|
Texture2D<snorm float4> ProbesData : register(t0);
|
||||||
Texture2D<float4> ProbesTrace : register(t1);
|
Texture2D<float4> ProbesTrace : register(t1);
|
||||||
ByteAddressBuffer ActiveProbes : register(t2);
|
ByteAddressBuffer ActiveProbes : register(t2);
|
||||||
|
|
||||||
@@ -348,13 +352,15 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
|
|||||||
|
|
||||||
// Skip disabled probes
|
// Skip disabled probes
|
||||||
bool skip = false;
|
bool skip = false;
|
||||||
float probeState = LoadDDGIProbeState(DDGI, ProbesState, CascadeIndex, probeIndex);
|
float4 probeData = LoadDDGIProbeData(DDGI, ProbesData, CascadeIndex, probeIndex);
|
||||||
|
uint probeState = DecodeDDGIProbeState(probeData);
|
||||||
|
uint probeRaysCount = GetProbeRaysCount(DDGI, probeState);
|
||||||
if (probeState == DDGI_PROBE_STATE_INACTIVE)
|
if (probeState == DDGI_PROBE_STATE_INACTIVE)
|
||||||
skip = true;
|
skip = true;
|
||||||
|
|
||||||
#if DDGI_PROBE_UPDATE_MODE == 0
|
#if DDGI_PROBE_UPDATE_MODE == 0
|
||||||
uint backfacesCount = 0;
|
uint backfacesCount = 0;
|
||||||
uint backfacesLimit = uint(DDGI.RaysCount * 0.1f);
|
uint backfacesLimit = uint(probeRaysCount * 0.1f);
|
||||||
#else
|
#else
|
||||||
float probesSpacing = DDGI.ProbesOriginAndSpacing[CascadeIndex].w;
|
float probesSpacing = DDGI.ProbesOriginAndSpacing[CascadeIndex].w;
|
||||||
float distanceLimit = length(probesSpacing) * 1.5f;
|
float distanceLimit = length(probesSpacing) * 1.5f;
|
||||||
@@ -364,9 +370,9 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
|
|||||||
if (!skip)
|
if (!skip)
|
||||||
{
|
{
|
||||||
// Load trace rays results into shared memory to reuse across whole thread group (raysCount per thread)
|
// Load trace rays results into shared memory to reuse across whole thread group (raysCount per thread)
|
||||||
uint raysCount = (uint)(ceil((float)DDGI.RaysCount / (float)(DDGI_PROBE_RESOLUTION * DDGI_PROBE_RESOLUTION)));
|
uint raysCount = (uint)(ceil((float)probeRaysCount / (float)(DDGI_PROBE_RESOLUTION * DDGI_PROBE_RESOLUTION)));
|
||||||
uint raysStart = GroupIndex * raysCount;
|
uint raysStart = GroupIndex * raysCount;
|
||||||
raysCount = max(min(raysStart + raysCount, DDGI.RaysCount), raysStart) - raysStart;
|
raysCount = max(min(raysStart + raysCount, probeRaysCount), raysStart) - raysStart;
|
||||||
for (uint i = 0; i < raysCount; i++)
|
for (uint i = 0; i < raysCount; i++)
|
||||||
{
|
{
|
||||||
uint rayIndex = raysStart + i;
|
uint rayIndex = raysStart + i;
|
||||||
@@ -392,7 +398,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
|
|||||||
// Loop over rays
|
// Loop over rays
|
||||||
float4 result = float4(0, 0, 0, 0);
|
float4 result = float4(0, 0, 0, 0);
|
||||||
LOOP
|
LOOP
|
||||||
for (uint rayIndex = 0; rayIndex < DDGI.RaysCount; rayIndex++)
|
for (uint rayIndex = 0; rayIndex < probeRaysCount; rayIndex++)
|
||||||
{
|
{
|
||||||
float3 rayDirection = CachedProbesTraceDirection[rayIndex];
|
float3 rayDirection = CachedProbesTraceDirection[rayIndex];
|
||||||
float rayWeight = max(dot(octahedralDirection, rayDirection), 0.0f);
|
float rayWeight = max(dot(octahedralDirection, rayDirection), 0.0f);
|
||||||
@@ -426,12 +432,12 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Normalize results
|
// Normalize results
|
||||||
float epsilon = (float)DDGI.RaysCount * 1e-9f;
|
float epsilon = (float)probeRaysCount * 1e-9f;
|
||||||
result.rgb *= 1.0f / (2.0f * max(result.a, epsilon));
|
result.rgb *= 1.0f / (2.0f * max(result.a, epsilon));
|
||||||
|
|
||||||
// Load current probe value
|
// Load current probe value
|
||||||
float3 previous = RWOutput[outputCoords].rgb;
|
float3 previous = RWOutput[outputCoords].rgb;
|
||||||
bool wasActivated = GetProbeState(probeState, DDGI_PROBE_STATE_ACTIVATED);
|
bool wasActivated = probeState == DDGI_PROBE_STATE_ACTIVATED;
|
||||||
if (ResetBlend || wasActivated)
|
if (ResetBlend || wasActivated)
|
||||||
previous = float3(0, 0, 0);
|
previous = float3(0, 0, 0);
|
||||||
|
|
||||||
@@ -541,7 +547,7 @@ void CS_UpdateBorders(uint3 DispatchThreadId : SV_DispatchThreadID)
|
|||||||
#include "./Flax/Random.hlsl"
|
#include "./Flax/Random.hlsl"
|
||||||
#include "./Flax/LightingCommon.hlsl"
|
#include "./Flax/LightingCommon.hlsl"
|
||||||
|
|
||||||
Texture2D<snorm float4> ProbesState : register(t4);
|
Texture2D<snorm float4> ProbesData : register(t4);
|
||||||
Texture2D<float4> ProbesDistance : register(t5);
|
Texture2D<float4> ProbesDistance : register(t5);
|
||||||
Texture2D<float4> ProbesIrradiance : register(t6);
|
Texture2D<float4> ProbesIrradiance : register(t6);
|
||||||
|
|
||||||
@@ -565,7 +571,7 @@ void PS_IndirectLighting(Quad_VS2PS input, out float4 output : SV_Target0)
|
|||||||
// Sample irradiance
|
// Sample irradiance
|
||||||
float bias = 0.2f;
|
float bias = 0.2f;
|
||||||
float dither = RandN2(input.TexCoord + TemporalTime).x;
|
float dither = RandN2(input.TexCoord + TemporalTime).x;
|
||||||
float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesState, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal, bias, dither);
|
float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesData, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal, bias, dither);
|
||||||
|
|
||||||
// Calculate lighting
|
// Calculate lighting
|
||||||
float3 diffuseColor = GetDiffuseColor(gBuffer);
|
float3 diffuseColor = GetDiffuseColor(gBuffer);
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ float4 PS_ClearLighting(AtlasVertexOutput input) : SV_Target
|
|||||||
// GBuffer+Depth at 0-3 slots
|
// GBuffer+Depth at 0-3 slots
|
||||||
Buffer<float4> GlobalSurfaceAtlasObjects : register(t4);
|
Buffer<float4> GlobalSurfaceAtlasObjects : register(t4);
|
||||||
#if INDIRECT_LIGHT
|
#if INDIRECT_LIGHT
|
||||||
Texture2D<snorm float4> ProbesState : register(t5);
|
Texture2D<snorm float4> ProbesData : register(t5);
|
||||||
Texture2D<float4> ProbesDistance : register(t6);
|
Texture2D<float4> ProbesDistance : register(t6);
|
||||||
Texture2D<float4> ProbesIrradiance : register(t7);
|
Texture2D<float4> ProbesIrradiance : register(t7);
|
||||||
#else
|
#else
|
||||||
@@ -134,7 +134,7 @@ float4 PS_Lighting(AtlasVertexOutput input) : SV_Target
|
|||||||
|
|
||||||
#if INDIRECT_LIGHT
|
#if INDIRECT_LIGHT
|
||||||
// Sample irradiance
|
// Sample irradiance
|
||||||
float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesState, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal);
|
float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesData, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal);
|
||||||
irradiance *= Light.Radius; // Cached BounceIntensity / IndirectLightingIntensity
|
irradiance *= Light.Radius; // Cached BounceIntensity / IndirectLightingIntensity
|
||||||
|
|
||||||
// Calculate lighting
|
// Calculate lighting
|
||||||
|
|||||||
@@ -286,7 +286,7 @@ Texture3D<float4> LightScatteringHistory : register(t2);
|
|||||||
Texture3D<float4> LocalShadowedLightScattering : register(t3);
|
Texture3D<float4> LocalShadowedLightScattering : register(t3);
|
||||||
Texture2DArray ShadowMapCSM : register(t4);
|
Texture2DArray ShadowMapCSM : register(t4);
|
||||||
#if USE_DDGI
|
#if USE_DDGI
|
||||||
Texture2D<snorm float4> ProbesState : register(t5);
|
Texture2D<snorm float4> ProbesData : register(t5);
|
||||||
Texture2D<float4> ProbesDistance : register(t6);
|
Texture2D<float4> ProbesDistance : register(t6);
|
||||||
Texture2D<float4> ProbesIrradiance : register(t7);
|
Texture2D<float4> ProbesIrradiance : register(t7);
|
||||||
#else
|
#else
|
||||||
@@ -337,7 +337,7 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_
|
|||||||
|
|
||||||
#if USE_DDGI
|
#if USE_DDGI
|
||||||
// Dynamic Diffuse Global Illumination
|
// Dynamic Diffuse Global Illumination
|
||||||
float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesState, ProbesDistance, ProbesIrradiance, positionWS, cameraVectorNormalized, 0.0f, cellOffset.x);
|
float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesData, ProbesDistance, ProbesIrradiance, positionWS, cameraVectorNormalized, 0.0f, cellOffset.x);
|
||||||
lightScattering += float4(irradiance, 1);
|
lightScattering += float4(irradiance, 1);
|
||||||
#else
|
#else
|
||||||
// Sky light
|
// Sky light
|
||||||
|
|||||||
Reference in New Issue
Block a user