Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 48 additions & 33 deletions features/Skylighting/Shaders/Skylighting/Skylighting.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ namespace Skylighting
Texture3D<sh2> SkylightingProbeArray : register(t50);
#endif

#if defined(SKYLIGHTING_SHADOW_VIS)
Texture3D<float> ShadowVisibilityProbeArray : register(t53);
#endif

const static sh2 UNIT_SH = float4(sqrt(4.0 * Math::PI), 0, 0, 0);

const static uint3 ARRAY_DIM = uint3(256, 256, 128);
Expand Down Expand Up @@ -75,10 +79,18 @@ namespace Skylighting
#endif

#if defined(PSHADER) || defined(SKYLIGHTING_PROBE_REGISTER)
sh2 Sample(float3 positionMS, float3 normalWS)
sh2 Sample(float3 positionMS, float3 normalWS
#if defined(SKYLIGHTING_SHADOW_VIS)
, out float shadowVisibility
#endif
)
{
sh2 scaledUnitSH = UNIT_SH / 1e-10;

#if defined(SKYLIGHTING_SHADOW_VIS)
shadowVisibility = 1.0;
#endif

if (SharedData::InInterior)
return scaledUnitSH;

Expand All @@ -94,55 +106,63 @@ namespace Skylighting
int3 cell000 = floor(cellVxCoord - 0.5);
float3 trilinearPos = cellVxCoord - 0.5 - cell000;

sh2 sum = 0;
float wsum = 0;
sh2 shSum = 0;
float shWsum = 0;
#if defined(SKYLIGHTING_SHADOW_VIS)
float shadowSum = 0;
float shadowWsum = 0;
#endif

for (int i = 0; i < 2; i++)
for (int j = 0; j < 2; j++)
for (int k = 0; k < 2; k++) {
int3 offset = int3(i, j, k);
int3 cellID = cell000 + offset;
int3 cellOffset = int3(i, j, k);
int3 cellID = cell000 + cellOffset;

if (any(cellID < 0) || any((uint3)cellID >= ARRAY_DIM))
continue;

float3 cellCentreMS = cellID + 0.5 - ARRAY_DIM / 2;
cellCentreMS = cellCentreMS * CELL_SIZE;
float3 cellCentreMS = (cellID + 0.5 - ARRAY_DIM / 2) * CELL_SIZE;

float3 trilinearWeights = 1 - abs(cellOffset - trilinearPos);
float triW = trilinearWeights.x * trilinearWeights.y * trilinearWeights.z;

uint3 cellTexID = (cellID + SharedData::skylightingSettings.ArrayOrigin.xyz) % ARRAY_DIM;

// https://handmade.network/p/75/monter/blog/p/7288-engine_work__global_illumination_with_irradiance_probes
// basic tangent checks
float tangentWeight = dot(normalize(cellCentreMS - positionMSAdjusted), normalWS) * 0.5 + 0.5;
float shW = triW * tangentWeight;
shSum = SphericalHarmonics::Add(shSum, SphericalHarmonics::Scale(SkylightingProbeArray[cellTexID], shW));
shWsum += shW;

float3 trilinearWeights = 1 - abs(offset - trilinearPos);
float w = trilinearWeights.x * trilinearWeights.y * trilinearWeights.z * tangentWeight;

uint3 cellTexID = (cellID + SharedData::skylightingSettings.ArrayOrigin.xyz) % ARRAY_DIM;
sh2 probe = SphericalHarmonics::Scale(SkylightingProbeArray[cellTexID], w);

sum = SphericalHarmonics::Add(sum, probe);
wsum += w;
#if defined(SKYLIGHTING_SHADOW_VIS)
shadowSum += ShadowVisibilityProbeArray[cellTexID] * triW;
shadowWsum += triW;
#endif
}

return SphericalHarmonics::Scale(sum, rcp(wsum + EPSILON_WEIGHT_SUM));
#if defined(SKYLIGHTING_SHADOW_VIS)
float fadeOut = GetFadeOutFactor(positionMS);
shadowVisibility = lerp(1.0, shadowSum / max(shadowWsum, EPSILON_WEIGHT_SUM), fadeOut);
#endif

return SphericalHarmonics::Scale(shSum, rcp(shWsum + EPSILON_WEIGHT_SUM));
}

// Compute skylighting diffuse for a receiver biased to face upward (grass/foliage).
// The result is pre-divided by vertexAO so that a subsequent multiply by vertexAO
// yields min(skylightingDiffuse, vertexAO). Pass vertexAO = 1 to skip this compensation.
float GetVertexSkylightingDiffuse(float3 positionMS, float3 normalWS, float vertexAO)
float GetSkylightingDiffuse(sh2 skylightingSH, float3 positionMS, float3 evalNormal, float vertexAO = 1.0)
{
if (SharedData::InInterior)
return 1.0;

float3 candidateNormal = float3(evalNormal.xy, max(0.0, evalNormal.z));
float3 biasedNormal = dot(candidateNormal, candidateNormal) > 1e-6
? normalize(candidateNormal)
: float3(0, 0, 1);
float fadeOutFactor = GetFadeOutFactor(positionMS);

float3 biasedNormal = normalWS;
biasedNormal.z = max(0.0, biasedNormal.z);
biasedNormal = normalize(biasedNormal);

sh2 skylightingSH = Sample(positionMS, normalWS);
float skylightingDiffuse = EvaluateDiffuse(skylightingSH, biasedNormal, fadeOutFactor);

return saturate(skylightingDiffuse / max(vertexAO, 1e-5));
return saturate(skylightingDiffuse / max(vertexAO, EPSILON_DIVISION));
}

sh2 SampleNoBias(float3 positionMS)
Expand Down Expand Up @@ -174,16 +194,11 @@ namespace Skylighting
if (any(cellID < 0) || any((uint3)cellID >= ARRAY_DIM))
continue;

float3 cellCentreMS = cellID + 0.5 - ARRAY_DIM / 2;
cellCentreMS = cellCentreMS * CELL_SIZE;

float3 trilinearWeights = 1 - abs(offset - trilinearPos);
float w = trilinearWeights.x * trilinearWeights.y * trilinearWeights.z;

uint3 cellTexID = (cellID + SharedData::skylightingSettings.ArrayOrigin.xyz) % ARRAY_DIM;
sh2 probe = SphericalHarmonics::Scale(SkylightingProbeArray[cellTexID], w);

sum = SphericalHarmonics::Add(sum, probe);
sum = SphericalHarmonics::Add(sum, SphericalHarmonics::Scale(SkylightingProbeArray[cellTexID], w));
wsum += w;
}

Expand Down
93 changes: 92 additions & 1 deletion features/Skylighting/Shaders/Skylighting/UpdateProbesCS.hlsl
Original file line number Diff line number Diff line change
@@ -1,13 +1,61 @@
#include "Common/FrameBuffer.hlsli"
#include "Common/Math.hlsli"
#include "Skylighting/Skylighting.hlsli"

Texture2D<unorm float> srcOcclusionDepth : register(t0);
Texture2DArray<float4> ShadowCascadeMap : register(t1);

struct DirectionalShadowLightData
{
column_major float4x4 ShadowProj[2];
column_major float4x4 InvShadowProj[2];
float2 EndSplitDistances;
float2 StartSplitDistances;
};
StructuredBuffer<DirectionalShadowLightData> DirectionalShadowLights : register(t2);
Comment thread
coderabbitai[bot] marked this conversation as resolved.

RWTexture3D<sh2> outProbeArray : register(u0);
RWTexture3D<uint> outAccumFramesArray : register(u1);
RWTexture3D<uint> outShadowBitmask : register(u2);
RWTexture3D<float> outShadowVisibility : register(u3);

SamplerComparisonState comparisonSampler : register(s0);

static const float3 noise3D[32] = {
float3(0.247, -0.583, 0.891),
float3(-0.672, 0.315, -0.428),
float3(0.934, 0.762, -0.153),
float3(-0.391, -0.847, 0.526),
float3(0.618, 0.094, 0.739),
float3(-0.825, -0.271, -0.683),
float3(0.152, 0.968, 0.347),
float3(0.503, -0.714, -0.592),
float3(-0.436, 0.629, 0.814),
float3(0.887, -0.198, 0.461),
float3(-0.759, 0.852, -0.305),
float3(0.321, -0.476, -0.921),
float3(-0.094, 0.543, -0.768),
float3(0.776, 0.418, 0.632),
float3(-0.538, -0.695, 0.279),
float3(0.649, -0.921, 0.186),
float3(-0.913, 0.127, 0.574),
float3(0.285, 0.806, -0.447),
float3(0.471, -0.352, 0.698),
float3(-0.627, -0.194, -0.856),
float3(0.834, 0.591, -0.712),
float3(-0.173, -0.968, -0.421),
float3(0.562, 0.239, -0.785),
float3(-0.745, 0.487, 0.316),
float3(0.108, -0.631, 0.894),
float3(0.926, -0.845, -0.267),
float3(-0.384, 0.712, -0.539),
float3(0.697, 0.163, 0.825),
float3(-0.851, -0.429, 0.641),
float3(0.214, 0.934, 0.372),
float3(0.578, -0.762, -0.614),
float3(-0.469, 0.381, 0.947)
};

[numthreads(8, 8, 1)] void main(uint3 dtid : SV_DispatchThreadID) {
const float fadeInThreshold = 15;
const static sh2 unitSH = Skylighting::UNIT_SH;
Expand Down Expand Up @@ -39,8 +87,51 @@ SamplerComparisonState comparisonSampler : register(s0);

outProbeArray[dtid] = occlusionSH;
outAccumFramesArray[dtid] = accumFrames;

// Shadow cascade sampling with bitmask accumulation
{
float shadowSample = 1.0;
DirectionalShadowLightData shadowData = DirectionalShadowLights[0];

uint shadowFrames = max(accumFrames, 1u);
uint bitIndex = (shadowFrames - 1) % 32;
float3 jitteredMS = cellCentreMS + noise3D[bitIndex] * Skylighting::CELL_SIZE;

float ndcDepth = FrameBuffer::GetShadowDepth(jitteredMS);
float linearDepth = SharedData::GetScreenDepth(ndcDepth);

if (linearDepth > 0 && linearDepth < shadowData.EndSplitDistances.y) {
float3 positionWS = jitteredMS + FrameBuffer::CameraPosAdjust.xyz;

uint cascadeIndex = (linearDepth > shadowData.EndSplitDistances.x) ? 1u : 0u;

float3 positionLS = mul(shadowData.ShadowProj[cascadeIndex], float4(positionWS, 1)).xyz;

if (all(positionLS.xy >= 0) && all(positionLS.xy <= 1)) {
shadowSample = ShadowCascadeMap.SampleCmpLevelZero(comparisonSampler, float3(positionLS.xy, cascadeIndex), positionLS.z);
}

float fade = saturate(linearDepth / shadowData.EndSplitDistances.y);
float fadeFactor = 1.0 - pow(fade * fade, 8);
shadowSample = lerp(1.0, shadowSample, fadeFactor);
}

uint bitmask = isValid ? outShadowBitmask[dtid] : 0;
bitmask &= ~(1u << bitIndex);
if (shadowSample > 0.5)
bitmask |= (1u << bitIndex);

outShadowBitmask[dtid] = bitmask;

uint validBits = min(shadowFrames, 32u);
float shadow = float(countbits(bitmask)) / float(validBits);
shadow = lerp(1.0, shadow, min(fadeInThreshold, shadowFrames) / fadeInThreshold);
outShadowVisibility[dtid] = shadow;
}
} else if (!isValid) {
outProbeArray[dtid] = unitSH;
outAccumFramesArray[dtid] = 0;
outShadowBitmask[dtid] = 0;
outShadowVisibility[dtid] = 1.0;
}
}
}
40 changes: 33 additions & 7 deletions package/Shaders/Lighting.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,12 @@ float GetSnowParameterY(float texProjTmp, float alpha)
# undef SKYLIGHTING
# endif

# if defined(SKYLIGHTING)
# if defined(RIM_LIGHTING) || defined(SOFT_LIGHTING) || defined(LOAD_SOFT_LIGHTING) || defined(BACK_LIGHTING)
# define SKYLIGHTING_SHADOW_VIS
# endif
# endif

# include "Common/LightingCommon.hlsli"

# if defined(WATER_EFFECTS)
Expand Down Expand Up @@ -2408,12 +2414,22 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)

# if defined(SKYLIGHTING)
float3 positionMSSkylight = input.WorldPosition.xyz;
# if defined(SKYLIGHTING_SHADOW_VIS)
float skylightingShadowVisibility = 1.0;
# endif
# if defined(DEFERRED)
sh2 skylightingSH = Skylighting::Sample(positionMSSkylight, worldNormal);
sh2 skylightingSH = Skylighting::Sample(positionMSSkylight, worldNormal
# if defined(SKYLIGHTING_SHADOW_VIS)
, skylightingShadowVisibility
# endif
);
# else
sh2 skylightingSH = inWorld ? Skylighting::Sample(positionMSSkylight, worldNormal) : Skylighting::UNIT_SH;
sh2 skylightingSH = inWorld ? Skylighting::Sample(positionMSSkylight, worldNormal
# if defined(SKYLIGHTING_SHADOW_VIS)
, skylightingShadowVisibility
# endif
) : Skylighting::UNIT_SH;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
# endif

# endif

float4 waterData = SharedData::GetWaterData(input.WorldPosition.xyz);
Expand Down Expand Up @@ -2561,22 +2577,28 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
float dirSoftShadow = 1.0;
float dirVSMDetailedShadow = 1.0;

# if defined(VOLUMETRIC_SHADOWS)
# if defined(VOLUMETRIC_SHADOWS) && !(defined(DEFERRED) && defined(SKYLIGHTING_SHADOW_VIS))
if (inWorld && !inReflection && ShadowSampling::HasDirectionalShadows())
dirSoftShadow = ShadowSampling::GetLightingShadow(input.WorldPosition.xyz, dirVSMDetailedShadow);
# if !defined(SKYLIGHTING_SHADOW_VIS)
dirSoftShadow =
# endif
ShadowSampling::GetLightingShadow(input.WorldPosition.xyz, dirVSMDetailedShadow);
# endif

float dirDetailedShadow = 1.0;

if ((Permutation::PixelShaderDescriptor & Permutation::LightingFlags::DefShadow) && (Permutation::PixelShaderDescriptor & Permutation::LightingFlags::ShadowDir)) {
dirDetailedShadow *= shadowColor.x;

# if !defined(VOLUMETRIC_SHADOWS)
# if !defined(VOLUMETRIC_SHADOWS) && !defined(SKYLIGHTING_SHADOW_VIS)
dirSoftShadow = dirDetailedShadow;
# endif
} else {
}
# if !defined(DEFERRED)
else {
dirDetailedShadow = dirVSMDetailedShadow;
}
# endif

# if defined(SCREEN_SPACE_SHADOWS) && defined(DEFERRED)
if (!SharedData::InInterior && dirLightAngle >= 0.0)
Expand Down Expand Up @@ -2626,6 +2648,10 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)
}
# endif

# if defined(SKYLIGHTING_SHADOW_VIS)
dirSoftShadow = skylightingShadowVisibility;
# endif

float3 diffuseColor = 0.0.xxx;
float3 specularColor = 0.0.xxx;
float3 transmissionColor = 0.0.xxx;
Expand Down
6 changes: 4 additions & 2 deletions package/Shaders/RunGrass.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,8 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace : SV_IsFrontFace)

# if defined(SKYLIGHTING)
float3 positionMSSkylight = input.WorldPosition.xyz;
float skylightingDiffuse = Skylighting::GetVertexSkylightingDiffuse(positionMSSkylight, normal, vertexAO);
sh2 skylightingSH = Skylighting::Sample(positionMSSkylight, normal);
float skylightingDiffuse = Skylighting::GetSkylightingDiffuse(skylightingSH, positionMSSkylight, normal, vertexAO);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
# endif // SKYLIGHTING

float3 albedo = baseColor.xyz * vertexColor;
Expand Down Expand Up @@ -820,7 +821,8 @@ PS_OUTPUT main(PS_INPUT input)

# if defined(SKYLIGHTING)
float3 positionMSSkylight = input.WorldPosition.xyz;
float skylightingDiffuse = Skylighting::GetVertexSkylightingDiffuse(positionMSSkylight, normal, vertexAO);
sh2 skylightingSH = Skylighting::Sample(positionMSSkylight, normal);
float skylightingDiffuse = Skylighting::GetSkylightingDiffuse(skylightingSH, positionMSSkylight, normal, vertexAO);
# endif // SKYLIGHTING

float3 directionalAmbientColor = Color::Ambient(max(0, SharedData::GetAmbient(normal)));
Expand Down
Loading
Loading