Refactor DDGI probes to use variable ray count depending on the probe location relative to the view frustum
This commit is contained in:
@@ -13,9 +13,9 @@
|
||||
#include "./Flax/Math.hlsl"
|
||||
#include "./Flax/Octahedral.hlsl"
|
||||
|
||||
#define DDGI_PROBE_STATE_INACTIVE 0.0f
|
||||
#define DDGI_PROBE_STATE_ACTIVATED 0.2f
|
||||
#define DDGI_PROBE_STATE_ACTIVE 1.0f
|
||||
#define DDGI_PROBE_STATE_INACTIVE 0
|
||||
#define DDGI_PROBE_STATE_ACTIVATED 1
|
||||
#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_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
|
||||
@@ -89,22 +89,32 @@ float3 GetDDGIProbeWorldPosition(DDGIData data, uint cascadeIndex, uint3 probeCo
|
||||
return probesOrigin + probePosition - probeGridOffset + (data.ProbesScrollOffsets[cascadeIndex].xyz * probesSpacing);
|
||||
}
|
||||
|
||||
// Loads probe probe state
|
||||
float LoadDDGIProbeState(DDGIData data, Texture2D<snorm float4> probesState, uint cascadeIndex, uint probeIndex)
|
||||
// Loads probe probe data (encoded)
|
||||
float4 LoadDDGIProbeData(DDGIData data, Texture2D<snorm float4> probesData, uint cascadeIndex, uint probeIndex)
|
||||
{
|
||||
int2 probeDataCoords = GetDDGIProbeTexelCoords(data, cascadeIndex, probeIndex);
|
||||
float4 probeState = probesState.Load(int3(probeDataCoords, 0));
|
||||
return probeState.w;
|
||||
return probesData.Load(int3(probeDataCoords, 0));
|
||||
}
|
||||
|
||||
// Loads probe world-space position (XYZ) and probe state (W)
|
||||
float4 LoadDDGIProbePositionAndState(DDGIData data, Texture2D<snorm float4> probesState, uint cascadeIndex, uint probeIndex, uint3 probeCoords)
|
||||
// Encodes probe probe data
|
||||
float4 EncodeDDGIProbeData(float3 probeOffset, uint probeState)
|
||||
{
|
||||
int2 probeDataCoords = GetDDGIProbeTexelCoords(data, cascadeIndex, probeIndex);
|
||||
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
|
||||
return probeState;
|
||||
return float4(probeOffset, (float)probeState * (1.0f / 8.0f));
|
||||
}
|
||||
|
||||
// Decodes probe state from the encoded state
|
||||
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)
|
||||
@@ -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.
|
||||
// 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<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
|
||||
uint cascadeIndex = 0;
|
||||
float4 probeStates[8];
|
||||
float4 probesDatas[8];
|
||||
for (; cascadeIndex < data.CascadesCount; cascadeIndex++)
|
||||
{
|
||||
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 probeCoords = clamp(baseProbeCoords + probeCoordsOffset, uint3(0, 0, 0), data.ProbesCounts - uint3(1, 1, 1));
|
||||
uint probeIndex = GetDDGIScrollingProbeIndex(data, cascadeIndex, probeCoords);
|
||||
float4 probeState = probesState.Load(int3(GetDDGIProbeTexelCoords(data, cascadeIndex, probeIndex), 0));
|
||||
probeStates[i] = probeState;
|
||||
if (probeState.w != DDGI_PROBE_STATE_INACTIVE)
|
||||
float4 probeData = LoadDDGIProbeData(data, probesData, cascadeIndex, probeIndex);
|
||||
probesDatas[i] = probeData;
|
||||
uint probeState = DecodeDDGIProbeState(probeData);
|
||||
if (probeState != DDGI_PROBE_STATE_INACTIVE)
|
||||
activeCount++;
|
||||
}
|
||||
|
||||
@@ -182,12 +193,12 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesState,
|
||||
uint probeIndex = GetDDGIScrollingProbeIndex(data, cascadeIndex, probeCoords);
|
||||
|
||||
// Load probe position and state
|
||||
float4 probeState = probeStates[i];
|
||||
if (probeState.w == DDGI_PROBE_STATE_INACTIVE)
|
||||
float4 probeData = probesDatas[i];
|
||||
uint probeState = DecodeDDGIProbeState(probeData);
|
||||
if (probeState == DDGI_PROBE_STATE_INACTIVE)
|
||||
continue;
|
||||
probeState.xyz *= probesSpacing; // Probe offset is [-1;1] within probes spacing
|
||||
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
|
||||
float3 worldPosToProbe = normalize(probePosition - worldPosition);
|
||||
@@ -233,7 +244,7 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesState,
|
||||
#endif
|
||||
|
||||
// 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
|
||||
irradiance += float4(probeIrradiance * weight, weight);
|
||||
|
||||
@@ -58,17 +58,18 @@ float3 GetProbeRayDirection(DDGIData data, uint rayIndex)
|
||||
return normalize(QuaternionRotate(data.RaysRotation, direction));
|
||||
}
|
||||
|
||||
// Checks if the probe states are equal
|
||||
bool GetProbeState(float a, float b)
|
||||
// Calculates amount of rays to allocate for a probe
|
||||
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
|
||||
|
||||
#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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// 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)
|
||||
[numthreads(DDGI_PROBE_CLASSIFY_GROUP_SIZE, 1, 1)]
|
||||
void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
||||
@@ -94,14 +95,15 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
||||
float probesSpacing = DDGI.ProbesOriginAndSpacing[CascadeIndex].w;
|
||||
|
||||
// Load probe state and position
|
||||
float4 probeState = RWProbesState[probeDataCoords];
|
||||
probeState.xyz *= probesSpacing; // Probe offset is [-1;1] within probes spacing
|
||||
float4 probeData = RWProbesData[probeDataCoords];
|
||||
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 probePosition = probeBasePosition;
|
||||
#if DDGI_PROBE_RELOCATE_ITERATIVE
|
||||
probePosition += probeState.xyz;
|
||||
probePosition += probeOffset;
|
||||
#endif
|
||||
float4 probeStateOld = probeState;
|
||||
|
||||
// Use Global SDF to quickly get distance and direction to the scene geometry
|
||||
#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
|
||||
{
|
||||
// Disable it
|
||||
probeState = float4(0, 0, 0, DDGI_PROBE_STATE_INACTIVE);
|
||||
probeOffset = float3(0, 0, 0);
|
||||
probeState = DDGI_PROBE_STATE_INACTIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -127,22 +130,22 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
||||
if (sdfDst < relocateLimit)
|
||||
{
|
||||
float3 offsetToAdd = sdfNormal * (sdf + threshold);
|
||||
if (distance(probeState.xyz, offsetToAdd) < relocateLimit)
|
||||
if (distance(probeOffset, offsetToAdd) < relocateLimit)
|
||||
{
|
||||
// Relocate it
|
||||
probeState.xyz += offsetToAdd;
|
||||
probeOffset += offsetToAdd;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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
|
||||
{
|
||||
// Reset relocation
|
||||
probeState.xyz = float3(0, 0, 0);
|
||||
probeOffset = float3(0, 0, 0);
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
// Reset relocation
|
||||
probeState.xyz = float3(0, 0, 0);
|
||||
probeOffset = float3(0, 0, 0);
|
||||
}
|
||||
#else
|
||||
// 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)
|
||||
if (bestOffset.w <= threshold)
|
||||
bestOffset.xyz = float3(0, 0, 0);
|
||||
probeState.xyz = bestOffset.xyz;
|
||||
probeOffset = bestOffset.xyz;
|
||||
#endif
|
||||
|
||||
// Check if probe was scrolled
|
||||
@@ -189,23 +192,21 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID)
|
||||
int probeCount = (int)DDGI.ProbesCounts[planeIndex];
|
||||
int newCord = (int)probeCoords[planeIndex] + probeScrollClears[planeIndex];
|
||||
if (newCord < 0 || newCord >= probeCount)
|
||||
{
|
||||
wasScrolled = true;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 wasRelocated = distance(probeState.xyz, probeStateOld.xyz) > 2.0f;
|
||||
probeState.w = wasInactive || wasScrolled || wasRelocated ? DDGI_PROBE_STATE_ACTIVATED : DDGI_PROBE_STATE_ACTIVE;
|
||||
bool wasInactive = probeState == DDGI_PROBE_STATE_INACTIVE;
|
||||
bool wasRelocated = distance(probeOffset, probeOffsetOld) > 2.0f;
|
||||
probeState = wasInactive || wasScrolled || wasRelocated ? DDGI_PROBE_STATE_ACTIVATED : DDGI_PROBE_STATE_ACTIVE;
|
||||
}
|
||||
|
||||
// Save probe state
|
||||
probeState.xyz /= probesSpacing;
|
||||
RWProbesState[probeDataCoords] = probeState;
|
||||
probeOffset /= probesSpacing; // Move offset back to [-1;1] space
|
||||
RWProbesData[probeDataCoords] = EncodeDDGIProbeData(probeOffset, probeState);
|
||||
|
||||
// Collect active probes
|
||||
if (probeState.w != DDGI_PROBE_STATE_INACTIVE)
|
||||
if (probeState != DDGI_PROBE_STATE_INACTIVE)
|
||||
{
|
||||
uint activeProbeIndex;
|
||||
RWActiveProbes.InterlockedAdd(0, 1, activeProbeIndex); // Counter at 0
|
||||
@@ -250,7 +251,7 @@ ByteAddressBuffer RWGlobalSurfaceAtlasCulledObjects : register(t3);
|
||||
Buffer<float4> GlobalSurfaceAtlasObjects : register(t4);
|
||||
Texture2D GlobalSurfaceAtlasDepth : register(t5);
|
||||
Texture2D GlobalSurfaceAtlasTex : register(t6);
|
||||
Texture2D<snorm float4> ProbesState : register(t7);
|
||||
Texture2D<snorm float4> ProbesData : register(t7);
|
||||
TextureCube Skybox : register(t8);
|
||||
ByteAddressBuffer ActiveProbes : register(t9);
|
||||
|
||||
@@ -269,14 +270,17 @@ void CS_TraceRays(uint3 DispatchThreadId : SV_DispatchThreadID)
|
||||
probeIndex = GetDDGIScrollingProbeIndex(DDGI, CascadeIndex, probeCoords);
|
||||
|
||||
// Load current probe state and position
|
||||
float4 probePositionAndState = LoadDDGIProbePositionAndState(DDGI, ProbesState, CascadeIndex, probeIndex, probeCoords);
|
||||
if (probePositionAndState.w == DDGI_PROBE_STATE_INACTIVE)
|
||||
return; // Skip disabled probes
|
||||
float4 probeData = LoadDDGIProbeData(DDGI, ProbesData, CascadeIndex, probeIndex);
|
||||
uint probeState = DecodeDDGIProbeState(probeData);
|
||||
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);
|
||||
|
||||
// Trace ray with Global SDF
|
||||
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);
|
||||
|
||||
// Calculate radiance and distance
|
||||
@@ -328,7 +332,7 @@ groupshared float CachedProbesTraceDistance[DDGI_TRACE_RAYS_LIMIT];
|
||||
groupshared float3 CachedProbesTraceDirection[DDGI_TRACE_RAYS_LIMIT];
|
||||
|
||||
RWTexture2D<float4> RWOutput : register(u0);
|
||||
Texture2D<snorm float4> ProbesState : register(t0);
|
||||
Texture2D<snorm float4> ProbesData : register(t0);
|
||||
Texture2D<float4> ProbesTrace : register(t1);
|
||||
ByteAddressBuffer ActiveProbes : register(t2);
|
||||
|
||||
@@ -348,13 +352,15 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
|
||||
|
||||
// Skip disabled probes
|
||||
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)
|
||||
skip = true;
|
||||
|
||||
#if DDGI_PROBE_UPDATE_MODE == 0
|
||||
uint backfacesCount = 0;
|
||||
uint backfacesLimit = uint(DDGI.RaysCount * 0.1f);
|
||||
uint backfacesLimit = uint(probeRaysCount * 0.1f);
|
||||
#else
|
||||
float probesSpacing = DDGI.ProbesOriginAndSpacing[CascadeIndex].w;
|
||||
float distanceLimit = length(probesSpacing) * 1.5f;
|
||||
@@ -364,9 +370,9 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
|
||||
if (!skip)
|
||||
{
|
||||
// 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;
|
||||
raysCount = max(min(raysStart + raysCount, DDGI.RaysCount), raysStart) - raysStart;
|
||||
raysCount = max(min(raysStart + raysCount, probeRaysCount), raysStart) - raysStart;
|
||||
for (uint i = 0; i < raysCount; i++)
|
||||
{
|
||||
uint rayIndex = raysStart + i;
|
||||
@@ -392,7 +398,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
|
||||
// Loop over rays
|
||||
float4 result = float4(0, 0, 0, 0);
|
||||
LOOP
|
||||
for (uint rayIndex = 0; rayIndex < DDGI.RaysCount; rayIndex++)
|
||||
for (uint rayIndex = 0; rayIndex < probeRaysCount; rayIndex++)
|
||||
{
|
||||
float3 rayDirection = CachedProbesTraceDirection[rayIndex];
|
||||
float rayWeight = max(dot(octahedralDirection, rayDirection), 0.0f);
|
||||
@@ -426,12 +432,12 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_
|
||||
}
|
||||
|
||||
// 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));
|
||||
|
||||
// Load current probe value
|
||||
float3 previous = RWOutput[outputCoords].rgb;
|
||||
bool wasActivated = GetProbeState(probeState, DDGI_PROBE_STATE_ACTIVATED);
|
||||
bool wasActivated = probeState == DDGI_PROBE_STATE_ACTIVATED;
|
||||
if (ResetBlend || wasActivated)
|
||||
previous = float3(0, 0, 0);
|
||||
|
||||
@@ -541,7 +547,7 @@ void CS_UpdateBorders(uint3 DispatchThreadId : SV_DispatchThreadID)
|
||||
#include "./Flax/Random.hlsl"
|
||||
#include "./Flax/LightingCommon.hlsl"
|
||||
|
||||
Texture2D<snorm float4> ProbesState : register(t4);
|
||||
Texture2D<snorm float4> ProbesData : register(t4);
|
||||
Texture2D<float4> ProbesDistance : register(t5);
|
||||
Texture2D<float4> ProbesIrradiance : register(t6);
|
||||
|
||||
@@ -565,7 +571,7 @@ void PS_IndirectLighting(Quad_VS2PS input, out float4 output : SV_Target0)
|
||||
// Sample irradiance
|
||||
float bias = 0.2f;
|
||||
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
|
||||
float3 diffuseColor = GetDiffuseColor(gBuffer);
|
||||
|
||||
@@ -87,7 +87,7 @@ float4 PS_ClearLighting(AtlasVertexOutput input) : SV_Target
|
||||
// GBuffer+Depth at 0-3 slots
|
||||
Buffer<float4> GlobalSurfaceAtlasObjects : register(t4);
|
||||
#if INDIRECT_LIGHT
|
||||
Texture2D<snorm float4> ProbesState : register(t5);
|
||||
Texture2D<snorm float4> ProbesData : register(t5);
|
||||
Texture2D<float4> ProbesDistance : register(t6);
|
||||
Texture2D<float4> ProbesIrradiance : register(t7);
|
||||
#else
|
||||
@@ -134,7 +134,7 @@ float4 PS_Lighting(AtlasVertexOutput input) : SV_Target
|
||||
|
||||
#if INDIRECT_LIGHT
|
||||
// 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
|
||||
|
||||
// Calculate lighting
|
||||
|
||||
Reference in New Issue
Block a user