124 lines
3.1 KiB
Plaintext
124 lines
3.1 KiB
Plaintext
[nzsl_version("1.0")]
|
|
module Engine.LightShadow;
|
|
|
|
option EnableShadowMapping: bool = true;
|
|
option MaxLightCascadeCount: u32 = u32(4); //< FIXME: Fix integral value types
|
|
|
|
import DirectionalLight, PointLight, SpotLight from Engine.LightData;
|
|
|
|
[export]
|
|
fn ComputeDirectionalLightShadow(light: DirectionalLight, shadowmap: depth_sampler2D_array[f32], worldPos: vec3[f32], lambert: f32, viewMatrix: mat4[f32]) -> f32
|
|
{
|
|
let shadowFactor = 1.0;
|
|
const if (EnableShadowMapping)
|
|
{
|
|
if (light.invShadowMapSize.x > 0.0)
|
|
{
|
|
let fragPosViewSpace = viewMatrix * vec4[f32](worldPos, 1.0);
|
|
let depthValue = abs(fragPosViewSpace.z);
|
|
|
|
let cascadeIndex = MaxLightCascadeCount;
|
|
for index in u32(0) -> light.cascadeCount
|
|
{
|
|
if (depthValue < light.cascadeDistances[index])
|
|
{
|
|
cascadeIndex = index;
|
|
break;
|
|
}
|
|
}
|
|
cascadeIndex = min(cascadeIndex, light.cascadeCount - u32(1));
|
|
|
|
let lightProjPos = light.viewProjMatrices[cascadeIndex] * vec4[f32](worldPos, 1.0);
|
|
let shadowCoords = lightProjPos.xyz / lightProjPos.w;
|
|
|
|
shadowFactor = 0.0;
|
|
[unroll]
|
|
for x in -1 -> 2
|
|
{
|
|
[unroll]
|
|
for y in -1 -> 2
|
|
{
|
|
let coords = shadowCoords.xy + vec2[f32](f32(x), f32(y)) * light.invShadowMapSize;
|
|
shadowFactor += shadowmap.SampleDepthComp(vec3[f32](coords, f32(cascadeIndex)), shadowCoords.z).r;
|
|
}
|
|
}
|
|
shadowFactor /= 9.0;
|
|
}
|
|
}
|
|
|
|
return shadowFactor;
|
|
}
|
|
|
|
[export]
|
|
fn ComputePointLightShadow(light: PointLight, shadowmap: sampler_cube[f32], dist: f32, lightDir: vec3[f32]) -> f32
|
|
{
|
|
let shadowFactor = 1.0;
|
|
const if (EnableShadowMapping)
|
|
{
|
|
if (light.invShadowMapSize.x > 0.0)
|
|
{
|
|
shadowFactor = 0.0;
|
|
|
|
let sampleDir = vec3[f32](lightDir.x, lightDir.y, -lightDir.z);
|
|
|
|
const sampleCount = 4;
|
|
const offset = 0.005;
|
|
|
|
const invSampleCount = 1.0 / f32(sampleCount);
|
|
const start = vec3[f32](offset * 0.5, offset * 0.5, offset * 0.5);
|
|
const shadowContribution = 1.0 / f32(sampleCount * sampleCount * sampleCount);
|
|
|
|
[unroll]
|
|
for x in 0 -> sampleCount
|
|
{
|
|
[unroll]
|
|
for y in 0 -> sampleCount
|
|
{
|
|
[unroll]
|
|
for z in 0 -> sampleCount
|
|
{
|
|
let dirOffset = vec3[f32](f32(x), f32(y), f32(z)) * invSampleCount * offset - start;
|
|
let sampleDir = sampleDir + dirOffset;
|
|
|
|
let closestDepth = shadowmap.Sample(sampleDir).r;
|
|
closestDepth *= light.radius;
|
|
|
|
if (closestDepth > dist)
|
|
shadowFactor += shadowContribution;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return shadowFactor;
|
|
}
|
|
|
|
[export]
|
|
fn ComputeSpotLightShadow(light: SpotLight, shadowmap: depth_sampler2D[f32], worldPos: vec3[f32], lambert: f32) -> f32
|
|
{
|
|
let shadowFactor = 1.0;
|
|
const if (EnableShadowMapping)
|
|
{
|
|
if (light.invShadowMapSize.x > 0.0)
|
|
{
|
|
let lightProjPos = light.viewProjMatrix * vec4[f32](worldPos, 1.0);
|
|
let shadowCoords = lightProjPos.xyz / lightProjPos.w;
|
|
|
|
shadowFactor = 0.0;
|
|
[unroll]
|
|
for x in -1 -> 2
|
|
{
|
|
[unroll]
|
|
for y in -1 -> 2
|
|
{
|
|
let coords = shadowCoords.xy + vec2[f32](f32(x), f32(y)) * light.invShadowMapSize;
|
|
shadowFactor += shadowmap.SampleDepthComp(coords, shadowCoords.z).r;
|
|
}
|
|
}
|
|
shadowFactor /= 9.0;
|
|
}
|
|
}
|
|
|
|
return shadowFactor;
|
|
} |