mirror of
https://github.com/barkeser2002/flower.git
synced 2026-09-25 18:56:16 +03:00
112 lines
3.3 KiB
GLSL
112 lines
3.3 KiB
GLSL
#ifndef SHADOW_COMMON_GLSL
|
|
#define SHADOW_COMMON_GLSL
|
|
|
|
#ifndef SHADOW_DEPTH_GATHER
|
|
#define SHADOW_DEPTH_GATHER 0
|
|
#endif
|
|
|
|
#ifndef SHADOW_COLOR
|
|
#define SHADOW_COLOR 0.99
|
|
#endif
|
|
|
|
#include "shared_functions.glsl"
|
|
|
|
// Surface normal based bias, see https://learn.microsoft.com/en-us/windows/win32/dxtecharts/cascaded-shadow-maps for more details.
|
|
vec3 biasNormalOffset(vec3 N, float NoL, float texelSize)
|
|
{
|
|
return N * clamp(1.0f - NoL, 0.0f, 1.0f) * texelSize * 30.0f;
|
|
}
|
|
|
|
// Auto bias by cacsade and NoL, some magic number here.
|
|
float autoBias(float NoL, float biasMul)
|
|
{
|
|
return 1e-3f + (1.0f - NoL) * biasMul * 2e-3f;
|
|
}
|
|
|
|
// Depth Aware Contact harden pcf. See GDC2021: "Shadows of Cold War" for tech detail.
|
|
// Use cache occluder dist to fit one curve similar to tonemapper, to get some effect like pcss.
|
|
// can reduce tiny acne natively.
|
|
float contactHardenPCFKernal(
|
|
const float occluders,
|
|
const float occluderDistSum,
|
|
const float compareDepth,
|
|
const uint shadowSampleCount)
|
|
{
|
|
// Normalize occluder dist.
|
|
float occluderAvgDist = occluderDistSum / occluders;
|
|
|
|
#if SHADOW_DEPTH_GATHER
|
|
float w = 1.0f / (4 * shadowSampleCount); // We gather 4 pixels.
|
|
#else
|
|
float w = 1.0f / (1 * shadowSampleCount);
|
|
#endif
|
|
|
|
float pcfWeight = clamp(occluderAvgDist / compareDepth, 0.0, 1.0);
|
|
|
|
// Normalize occluders.
|
|
float percentageOccluded = clamp(occluders * w, 0.0, 1.0);
|
|
|
|
// S curve fit.
|
|
percentageOccluded = 2.0f * percentageOccluded - 1.0f;
|
|
float occludedSign = sign(percentageOccluded);
|
|
percentageOccluded = 1.0f - (occludedSign * percentageOccluded);
|
|
percentageOccluded = mix(percentageOccluded * percentageOccluded * percentageOccluded, percentageOccluded, pcfWeight);
|
|
percentageOccluded = 1.0f - percentageOccluded;
|
|
percentageOccluded *= occludedSign;
|
|
percentageOccluded = 0.5f * percentageOccluded + 0.5f;
|
|
|
|
return 1.0f - percentageOccluded * SHADOW_COLOR;
|
|
}
|
|
|
|
float screenSpaceContactShadow(
|
|
texture2D inSceneDepth,
|
|
sampler inPointClampEdgeSampler,
|
|
in const PerFrameData inViewData,
|
|
float noise01,
|
|
uint stepNum,
|
|
vec3 wsRayStart,
|
|
vec3 wsRayDirection,
|
|
float wsRayLength)
|
|
{
|
|
// cast a ray in the direction of the light
|
|
float occlusion = 0.0;
|
|
|
|
ScreenSpaceRay rayData;
|
|
initScreenSpaceRay(rayData, wsRayStart, wsRayDirection, wsRayLength, inViewData);
|
|
|
|
// step
|
|
const uint kStepCount = stepNum;
|
|
const float dt = 1.0 / float(kStepCount);
|
|
|
|
// tolerance
|
|
const float tolerance = abs(rayData.ssViewRayEnd.z - rayData.ssRayStart.z) * dt;
|
|
|
|
// dither the ray with interleaved gradient noise
|
|
const float dither = noise01 - 0.5;
|
|
|
|
// normalized position on the ray (0 to 1)
|
|
float t = dt * dither + dt;
|
|
|
|
vec3 ray;
|
|
for (uint i = 0u ; i < kStepCount ; i++, t += dt)
|
|
{
|
|
ray = rayData.uvRayStart + rayData.uvRay * t;
|
|
float z = texture(sampler2D(inSceneDepth, inPointClampEdgeSampler), ray.xy).r;
|
|
float dz = z - ray.z;
|
|
if (abs(tolerance - dz) < tolerance)
|
|
{
|
|
occlusion = 1.0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// we fade out the contribution of contact shadows towards the edge of the screen
|
|
// because we don't have depth data there
|
|
vec2 fade = max(12.0 * abs(ray.xy - 0.5) - 5.0, 0.0);
|
|
occlusion *= saturate(1.0 - dot(fade, fade));
|
|
|
|
return occlusion;
|
|
}
|
|
|
|
|
|
#endif |