Add option for smooth DDGI cascades blending
This commit is contained in:
@@ -116,6 +116,12 @@ public:
|
|||||||
API_FIELD(Attributes="EditorOrder(2120), Limit(50, 1000), EditorDisplay(\"Global Illumination\")")
|
API_FIELD(Attributes="EditorOrder(2120), Limit(50, 1000), EditorDisplay(\"Global Illumination\")")
|
||||||
float GIProbesSpacing = 100;
|
float GIProbesSpacing = 100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables cascades splits blending for Global Illumination.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes="EditorOrder(2125), DefaultValue(false), EditorDisplay(\"Global Illumination\", \"GI Cascades Blending\")")
|
||||||
|
bool GICascadesBlending = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Global Surface Atlas resolution. Adjust it if atlas `flickers` due to overflow (eg. to 4096).
|
/// The Global Surface Atlas resolution. Adjust it if atlas `flickers` due to overflow (eg. to 4096).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -21,8 +21,9 @@ Quality Graphics::ShadowMapsQuality = Quality::Medium;
|
|||||||
bool Graphics::AllowCSMBlending = false;
|
bool Graphics::AllowCSMBlending = false;
|
||||||
Quality Graphics::GlobalSDFQuality = Quality::High;
|
Quality Graphics::GlobalSDFQuality = Quality::High;
|
||||||
Quality Graphics::GIQuality = Quality::High;
|
Quality Graphics::GIQuality = Quality::High;
|
||||||
|
bool Graphics::GICascadesBlending = false;
|
||||||
PostProcessSettings Graphics::PostProcessSettings;
|
PostProcessSettings Graphics::PostProcessSettings;
|
||||||
bool Graphics::SpreadWorkload = true;
|
bool Graphics::SpreadWorkload = false;
|
||||||
|
|
||||||
#if GRAPHICS_API_NULL
|
#if GRAPHICS_API_NULL
|
||||||
extern GPUDevice* CreateGPUDeviceNull();
|
extern GPUDevice* CreateGPUDeviceNull();
|
||||||
@@ -69,6 +70,7 @@ void GraphicsSettings::Apply()
|
|||||||
Graphics::ShadowMapsQuality = ShadowMapsQuality;
|
Graphics::ShadowMapsQuality = ShadowMapsQuality;
|
||||||
Graphics::GlobalSDFQuality = GlobalSDFQuality;
|
Graphics::GlobalSDFQuality = GlobalSDFQuality;
|
||||||
Graphics::GIQuality = GIQuality;
|
Graphics::GIQuality = GIQuality;
|
||||||
|
Graphics::GICascadesBlending = GICascadesBlending;
|
||||||
Graphics::PostProcessSettings = ::PostProcessSettings();
|
Graphics::PostProcessSettings = ::PostProcessSettings();
|
||||||
Graphics::PostProcessSettings.BlendWith(PostProcessSettings, 1.0f);
|
Graphics::PostProcessSettings.BlendWith(PostProcessSettings, 1.0f);
|
||||||
#if !USE_EDITOR // OptionsModule handles fallback fonts in Editor
|
#if !USE_EDITOR // OptionsModule handles fallback fonts in Editor
|
||||||
|
|||||||
@@ -64,6 +64,11 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
API_FIELD() static Quality GIQuality;
|
API_FIELD() static Quality GIQuality;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enables cascades splits blending for Global Illumination.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD() static bool GICascadesBlending;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The default Post Process settings. Can be overriden by PostFxVolume on a level locally, per camera or for a whole map.
|
/// The default Post Process settings. Can be overriden by PostFxVolume on a level locally, per camera or for a whole map.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -221,12 +221,16 @@ bool DynamicDiffuseGlobalIlluminationPass::setupResources()
|
|||||||
_csUpdateProbesDistance = shader->GetCS("CS_UpdateProbes", 1);
|
_csUpdateProbesDistance = shader->GetCS("CS_UpdateProbes", 1);
|
||||||
auto device = GPUDevice::Instance;
|
auto device = GPUDevice::Instance;
|
||||||
auto psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle;
|
auto psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle;
|
||||||
if (!_psIndirectLighting)
|
if (!_psIndirectLighting[0])
|
||||||
{
|
{
|
||||||
_psIndirectLighting = device->CreatePipelineState();
|
_psIndirectLighting[0] = device->CreatePipelineState();
|
||||||
|
_psIndirectLighting[1] = device->CreatePipelineState();
|
||||||
psDesc.PS = shader->GetPS("PS_IndirectLighting");
|
psDesc.PS = shader->GetPS("PS_IndirectLighting");
|
||||||
psDesc.BlendMode = BlendingMode::Add;
|
psDesc.BlendMode = BlendingMode::Add;
|
||||||
if (_psIndirectLighting->Init(psDesc))
|
if (_psIndirectLighting[0]->Init(psDesc))
|
||||||
|
return true;
|
||||||
|
psDesc.PS = shader->GetPS("PS_IndirectLighting", 1);
|
||||||
|
if (_psIndirectLighting[1]->Init(psDesc))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +250,8 @@ void DynamicDiffuseGlobalIlluminationPass::OnShaderReloading(Asset* obj)
|
|||||||
_csTraceRays[3] = nullptr;
|
_csTraceRays[3] = nullptr;
|
||||||
_csUpdateProbesIrradiance = nullptr;
|
_csUpdateProbesIrradiance = nullptr;
|
||||||
_csUpdateProbesDistance = nullptr;
|
_csUpdateProbesDistance = nullptr;
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psIndirectLighting);
|
SAFE_DELETE_GPU_RESOURCE(_psIndirectLighting[0]);
|
||||||
|
SAFE_DELETE_GPU_RESOURCE(_psIndirectLighting[1]);
|
||||||
invalidateResources();
|
invalidateResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +265,8 @@ void DynamicDiffuseGlobalIlluminationPass::Dispose()
|
|||||||
_cb0 = nullptr;
|
_cb0 = nullptr;
|
||||||
_cb1 = nullptr;
|
_cb1 = nullptr;
|
||||||
_shader = nullptr;
|
_shader = nullptr;
|
||||||
SAFE_DELETE_GPU_RESOURCE(_psIndirectLighting);
|
SAFE_DELETE_GPU_RESOURCE(_psIndirectLighting[0]);
|
||||||
|
SAFE_DELETE_GPU_RESOURCE(_psIndirectLighting[1]);
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
_debugModel = nullptr;
|
_debugModel = nullptr;
|
||||||
_debugMaterial = nullptr;
|
_debugMaterial = nullptr;
|
||||||
@@ -534,7 +540,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont
|
|||||||
// Update probes
|
// Update probes
|
||||||
{
|
{
|
||||||
PROFILE_GPU_CPU_NAMED("Probes Update");
|
PROFILE_GPU_CPU_NAMED("Probes Update");
|
||||||
uint32 threadGroupsX, threadGroupsY;
|
uint32 threadGroupsX;
|
||||||
#if DDGI_DEBUG_STATS
|
#if DDGI_DEBUG_STATS
|
||||||
uint32 zero[4] = {};
|
uint32 zero[4] = {};
|
||||||
context->ClearUA(ddgiData.StatsWrite, zero);
|
context->ClearUA(ddgiData.StatsWrite, zero);
|
||||||
@@ -732,7 +738,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext,
|
|||||||
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);
|
||||||
context->SetRenderTarget(lightBuffer);
|
context->SetRenderTarget(lightBuffer);
|
||||||
context->SetState(_psIndirectLighting);
|
context->SetState(_psIndirectLighting[Graphics::GICascadesBlending ? 1 : 0]);
|
||||||
context->DrawFullscreenTriangle();
|
context->DrawFullscreenTriangle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ private:
|
|||||||
GPUShaderProgramCS* _csTraceRays[4];
|
GPUShaderProgramCS* _csTraceRays[4];
|
||||||
GPUShaderProgramCS* _csUpdateProbesIrradiance;
|
GPUShaderProgramCS* _csUpdateProbesIrradiance;
|
||||||
GPUShaderProgramCS* _csUpdateProbesDistance;
|
GPUShaderProgramCS* _csUpdateProbesDistance;
|
||||||
GPUPipelineState* _psIndirectLighting;
|
GPUPipelineState* _psIndirectLighting[2] = {};
|
||||||
#if USE_EDITOR
|
#if USE_EDITOR
|
||||||
AssetReference<Model> _debugModel;
|
AssetReference<Model> _debugModel;
|
||||||
AssetReference<MaterialBase> _debugMaterial;
|
AssetReference<MaterialBase> _debugMaterial;
|
||||||
|
|||||||
@@ -21,6 +21,9 @@
|
|||||||
#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_CASCADE_BLEND_SIZE 2.5f // Distance in probes over which cascades blending happens
|
#define DDGI_CASCADE_BLEND_SIZE 2.5f // Distance in probes over which cascades blending happens
|
||||||
|
#ifndef DDGI_CASCADE_BLEND_SMOOTH
|
||||||
|
#define DDGI_CASCADE_BLEND_SMOOTH 0 // Enables smooth cascade blending, otherwise dithering will be used
|
||||||
|
#endif
|
||||||
#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
|
||||||
|
|
||||||
// DDGI data for a constant buffer
|
// DDGI data for a constant buffer
|
||||||
@@ -154,37 +157,8 @@ float2 GetDDGIProbeUV(DDGIData data, uint cascadeIndex, uint probeIndex, float2
|
|||||||
return uv;
|
return uv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Samples DDGI probes volume at the given world-space position and returns the irradiance.
|
float3 SampleDDGIIrradianceCascade(DDGIData data, Texture2D<snorm float4> probesData, Texture2D<float4> probesDistance, Texture2D<float4> probesIrradiance, float3 worldPosition, float3 worldNormal, uint cascadeIndex, float3 probesOrigin, float3 probesExtent, float probesSpacing, float3 biasedWorldPosition)
|
||||||
// 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> 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;
|
|
||||||
float probesSpacing = 0;
|
|
||||||
float3 probesOrigin = (float3)0, probesExtent = (float3)0, biasedWorldPosition = (float3)0;
|
|
||||||
float3 viewDir = normalize(data.ViewPos - worldPosition);
|
|
||||||
for (; cascadeIndex < data.CascadesCount; cascadeIndex++)
|
|
||||||
{
|
|
||||||
// Get cascade data
|
|
||||||
probesSpacing = data.ProbesOriginAndSpacing[cascadeIndex].w;
|
|
||||||
probesOrigin = data.ProbesScrollOffsets[cascadeIndex].xyz * probesSpacing + data.ProbesOriginAndSpacing[cascadeIndex].xyz;
|
|
||||||
probesExtent = (data.ProbesCounts - 1) * (probesSpacing * 0.5f);
|
|
||||||
|
|
||||||
// Bias the world-space position to reduce artifacts
|
|
||||||
float3 surfaceBias = (worldNormal * 0.2f + viewDir * 0.8f) * (0.75f * probesSpacing * bias);
|
|
||||||
biasedWorldPosition = worldPosition + surfaceBias;
|
|
||||||
|
|
||||||
// Calculate cascade blending weight (use input bias to smooth transition)
|
|
||||||
float cascadeBlendSmooth = frac(max(distance(data.ViewPos, worldPosition) - probesExtent.x, 0) / probesSpacing) * 0.1f;
|
|
||||||
float3 cascadeBlendPoint = worldPosition - probesOrigin - cascadeBlendSmooth * probesSpacing;
|
|
||||||
float fadeDistance = probesSpacing * DDGI_CASCADE_BLEND_SIZE;
|
|
||||||
float cascadeWeight = saturate(Min3(probesExtent - abs(cascadeBlendPoint)) / fadeDistance);
|
|
||||||
if (cascadeWeight > dither)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (cascadeIndex == data.CascadesCount)
|
|
||||||
return data.FallbackIrradiance;
|
|
||||||
uint3 probeCoordsEnd = data.ProbesCounts - uint3(1, 1, 1);
|
uint3 probeCoordsEnd = data.ProbesCounts - uint3(1, 1, 1);
|
||||||
uint3 baseProbeCoords = clamp(uint3((worldPosition - probesOrigin + probesExtent) / probesSpacing), uint3(0, 0, 0), probeCoordsEnd);
|
uint3 baseProbeCoords = clamp(uint3((worldPosition - probesOrigin + probesExtent) / probesSpacing), uint3(0, 0, 0), probeCoordsEnd);
|
||||||
|
|
||||||
@@ -208,25 +182,26 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesData, T
|
|||||||
{
|
{
|
||||||
// Search nearby probes to find any nearby GI sample
|
// Search nearby probes to find any nearby GI sample
|
||||||
for (int searchDistance = 1; searchDistance < 3 && probeState == DDGI_PROBE_STATE_INACTIVE; searchDistance++)
|
for (int searchDistance = 1; searchDistance < 3 && probeState == DDGI_PROBE_STATE_INACTIVE; searchDistance++)
|
||||||
for (uint searchAxis = 0; searchAxis < 3; searchAxis++)
|
for (uint searchAxis = 0; searchAxis < 3; searchAxis++)
|
||||||
{
|
|
||||||
int searchAxisDir = probeCoordsOffset[searchAxis] ? 1 : -1;
|
|
||||||
int3 searchCoordsOffset = SearchAxisMasks[searchAxis] * searchAxisDir * searchDistance;
|
|
||||||
uint3 searchCoords = clamp((int3)probeCoords + searchCoordsOffset, int3(0, 0, 0), (int3)probeCoordsEnd);
|
|
||||||
uint searchIndex = GetDDGIScrollingProbeIndex(data, cascadeIndex, searchCoords);
|
|
||||||
float4 searchData = LoadDDGIProbeData(data, probesData, cascadeIndex, searchIndex);
|
|
||||||
uint searchState = DecodeDDGIProbeState(searchData);
|
|
||||||
if (searchState != DDGI_PROBE_STATE_INACTIVE)
|
|
||||||
{
|
{
|
||||||
// Use nearby probe as a fallback (visibility test might ignore it but with smooth gradient)
|
int searchAxisDir = probeCoordsOffset[searchAxis] ? 1 : -1;
|
||||||
probeCoords = searchCoords;
|
int3 searchCoordsOffset = SearchAxisMasks[searchAxis] * searchAxisDir * searchDistance;
|
||||||
probeIndex = searchIndex;
|
uint3 searchCoords = clamp((int3)probeCoords + searchCoordsOffset, int3(0, 0, 0), (int3)probeCoordsEnd);
|
||||||
probeData = searchData;
|
uint searchIndex = GetDDGIScrollingProbeIndex(data, cascadeIndex, searchCoords);
|
||||||
probeState = searchState;
|
float4 searchData = LoadDDGIProbeData(data, probesData, cascadeIndex, searchIndex);
|
||||||
break;
|
uint searchState = DecodeDDGIProbeState(searchData);
|
||||||
|
if (searchState != DDGI_PROBE_STATE_INACTIVE)
|
||||||
|
{
|
||||||
|
// Use nearby probe as a fallback (visibility test might ignore it but with smooth gradient)
|
||||||
|
probeCoords = searchCoords;
|
||||||
|
probeIndex = searchIndex;
|
||||||
|
probeData = searchData;
|
||||||
|
probeState = searchState;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (probeState == DDGI_PROBE_STATE_INACTIVE)
|
||||||
if (probeState == DDGI_PROBE_STATE_INACTIVE) continue;
|
continue;
|
||||||
}
|
}
|
||||||
float3 probeBasePosition = baseProbeWorldPosition + ((probeCoords - baseProbeCoords) * probesSpacing);
|
float3 probeBasePosition = baseProbeWorldPosition + ((probeCoords - baseProbeCoords) * probesSpacing);
|
||||||
float3 probePosition = probeBasePosition + probeData.xyz * probesSpacing; // Probe offset is [-1;1] within probes spacing
|
float3 probePosition = probeBasePosition + probeData.xyz * probesSpacing; // Probe offset is [-1;1] within probes spacing
|
||||||
@@ -257,7 +232,8 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesData, T
|
|||||||
|
|
||||||
// Adjust weight curve to inject a small portion of light
|
// Adjust weight curve to inject a small portion of light
|
||||||
const float minWeightThreshold = 0.2f;
|
const float minWeightThreshold = 0.2f;
|
||||||
if (weight < minWeightThreshold) weight *= Square(weight) / Square(minWeightThreshold);
|
if (weight < minWeightThreshold)
|
||||||
|
weight *= Square(weight) / Square(minWeightThreshold);
|
||||||
|
|
||||||
// Calculate trilinear weights based on the distance to each probe to smoothly transition between grid of 8 probes
|
// Calculate trilinear weights based on the distance to each probe to smoothly transition between grid of 8 probes
|
||||||
float3 trilinear = lerp(1.0f - biasAlpha, biasAlpha, (float3)probeCoordsOffset);
|
float3 trilinear = lerp(1.0f - biasAlpha, biasAlpha, (float3)probeCoordsOffset);
|
||||||
@@ -301,3 +277,64 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D<snorm float4> probesData, T
|
|||||||
}
|
}
|
||||||
return irradiance.rgb;
|
return irradiance.rgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float3 GetDDGISurfaceBias(float3 viewDir, float probesSpacing, float3 worldNormal, float bias)
|
||||||
|
{
|
||||||
|
// Bias the world-space position to reduce artifacts
|
||||||
|
return (worldNormal * 0.2f + viewDir * 0.8f) * (0.75f * probesSpacing * bias);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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> 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;
|
||||||
|
float probesSpacing = 0, cascadeWeight = 0;
|
||||||
|
float3 probesOrigin = (float3)0, probesExtent = (float3)0, biasedWorldPosition = (float3)0;
|
||||||
|
float3 viewDir = normalize(data.ViewPos - worldPosition);
|
||||||
|
#if DDGI_CASCADE_BLEND_SMOOTH
|
||||||
|
dither = 0.0f;
|
||||||
|
#endif
|
||||||
|
for (; cascadeIndex < data.CascadesCount; cascadeIndex++)
|
||||||
|
{
|
||||||
|
// Get cascade data
|
||||||
|
probesSpacing = data.ProbesOriginAndSpacing[cascadeIndex].w;
|
||||||
|
probesOrigin = data.ProbesScrollOffsets[cascadeIndex].xyz * probesSpacing + data.ProbesOriginAndSpacing[cascadeIndex].xyz;
|
||||||
|
probesExtent = (data.ProbesCounts - 1) * (probesSpacing * 0.5f);
|
||||||
|
biasedWorldPosition = worldPosition + GetDDGISurfaceBias(viewDir, probesSpacing, worldNormal, bias);
|
||||||
|
|
||||||
|
// Calculate cascade blending weight (use input bias to smooth transition)
|
||||||
|
float cascadeBlendSmooth = frac(max(distance(data.ViewPos, worldPosition) - probesExtent.x, 0) / probesSpacing) * 0.1f;
|
||||||
|
float3 cascadeBlendPoint = worldPosition - probesOrigin - cascadeBlendSmooth * probesSpacing;
|
||||||
|
float fadeDistance = probesSpacing * DDGI_CASCADE_BLEND_SIZE;
|
||||||
|
#if DDGI_CASCADE_BLEND_SMOOTH
|
||||||
|
fadeDistance *= 2.0f; // Make it even smoother when using linear blending
|
||||||
|
#endif
|
||||||
|
cascadeWeight = saturate(Min3(probesExtent - abs(cascadeBlendPoint)) / fadeDistance);
|
||||||
|
if (cascadeWeight > dither)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cascadeIndex == data.CascadesCount)
|
||||||
|
return data.FallbackIrradiance;
|
||||||
|
|
||||||
|
// Sample cascade
|
||||||
|
float3 result = SampleDDGIIrradianceCascade(data, probesData, probesDistance, probesIrradiance, worldPosition, worldNormal, cascadeIndex, probesOrigin, probesExtent, probesSpacing, biasedWorldPosition);
|
||||||
|
|
||||||
|
#if DDGI_CASCADE_BLEND_SMOOTH
|
||||||
|
// Blend with the next cascade
|
||||||
|
cascadeIndex++;
|
||||||
|
if (cascadeIndex < data.CascadesCount && cascadeWeight < 0.99f)
|
||||||
|
{
|
||||||
|
probesSpacing = data.ProbesOriginAndSpacing[cascadeIndex].w;
|
||||||
|
probesOrigin = data.ProbesScrollOffsets[cascadeIndex].xyz * probesSpacing + data.ProbesOriginAndSpacing[cascadeIndex].xyz;
|
||||||
|
probesExtent = (data.ProbesCounts - 1) * (probesSpacing * 0.5f);
|
||||||
|
biasedWorldPosition = worldPosition + GetDDGISurfaceBias(viewDir, probesSpacing, worldNormal, bias);
|
||||||
|
float3 resultNext = SampleDDGIIrradianceCascade(data, probesData, probesDistance, probesIrradiance, worldPosition, worldNormal, cascadeIndex, probesOrigin, probesExtent, probesSpacing, biasedWorldPosition);
|
||||||
|
result = lerp(resultNext, result, cascadeWeight);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|||||||
@@ -768,6 +768,8 @@ Texture2D<float4> ProbesIrradiance : register(t6);
|
|||||||
|
|
||||||
// Pixel shader for drawing indirect lighting in fullscreen
|
// Pixel shader for drawing indirect lighting in fullscreen
|
||||||
META_PS(true, FEATURE_LEVEL_SM5)
|
META_PS(true, FEATURE_LEVEL_SM5)
|
||||||
|
META_PERMUTATION_1(DDGI_CASCADE_BLEND_SMOOTH=0)
|
||||||
|
META_PERMUTATION_1(DDGI_CASCADE_BLEND_SMOOTH=1)
|
||||||
void PS_IndirectLighting(Quad_VS2PS input, out float4 output : SV_Target0)
|
void PS_IndirectLighting(Quad_VS2PS input, out float4 output : SV_Target0)
|
||||||
{
|
{
|
||||||
output = 0;
|
output = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user