playcanvas
Version:
PlayCanvas WebGL game engine
197 lines (146 loc) • 8.54 kB
JavaScript
// functions used to evaluate the light shadow
var lightFunctionShadowPS = /* glsl */ `
// shadow casting functionality
// generate shadow coordinates function, based on per light defines:
// - _SHADOW_SAMPLE_NORMAL_OFFSET
// - _SHADOW_SAMPLE_ORTHO
// - _SHADOW_SAMPLE_POINT
// - _SHADOW_SAMPLE_SOURCE_ZBUFFER
vec3 getShadowSampleCoord{i}(mat4 shadowTransform, vec4 shadowParams, vec3 worldPosition, vec3 lightPos, inout vec3 lightDir, vec3 lightDirNorm, vec3 normal) {
vec3 surfacePosition = worldPosition;
float distScale = length(lightDir);
surfacePosition = surfacePosition + normal * shadowParams.y * clamp(1.0 - dot(normal, -lightDirNorm), 0.0, 1.0) * distScale;
lightDir = surfacePosition - lightPos;
return lightDir;
surfacePosition = surfacePosition + normal * shadowParams.y;
float distScale = 1.0;
float distScale = abs(dot(vPositionW - lightPos, lightDirNorm));
surfacePosition = surfacePosition + normal * shadowParams.y * clamp(1.0 - dot(normal, -lightDirNorm), 0.0, 1.0) * distScale;
vec4 positionInShadowSpace = shadowTransform * vec4(surfacePosition, 1.0);
positionInShadowSpace.z = saturate(positionInShadowSpace.z) - 0.0001;
positionInShadowSpace.xyz /= positionInShadowSpace.w;
positionInShadowSpace.xy /= positionInShadowSpace.w;
positionInShadowSpace.z = length(lightDir) * shadowParams.w;
// this is currently unused
// positionInShadowSpace.z += getShadowBias(shadowParams.x, shadowParams.z);
surfacePosition = positionInShadowSpace.xyz;
return surfacePosition;
}
// shadow evaluation function
float getShadow{i}(vec3 lightDirW) {
// directional shadow cascades
// select shadow cascade matrix
int cascadeIndex = getShadowCascadeIndex(light{i}_shadowCascadeDistances, light{i}_shadowCascadeCount);
cascadeIndex = ditherShadowCascadeIndex(cascadeIndex, light{i}_shadowCascadeDistances, light{i}_shadowCascadeCount, light{i}_shadowCascadeBlend);
mat4 shadowMatrix = light{i}_shadowMatrixPalette[cascadeIndex];
mat4 shadowMatrix = light{i}_shadowMatrix;
// directional light does not have a position
vec3 shadowCoord = getShadowSampleCoord{i}(shadowMatrix, light{i}_shadowParams, vPositionW, vec3(0.0), lightDirW, dLightDirNormW, dVertexNormalW);
vec3 shadowCoord = getShadowSampleCoord{i}(shadowMatrix, light{i}_shadowParams, vPositionW, light{i}_position, lightDirW, dLightDirNormW, dVertexNormalW);
// Fade directional shadow at the far distance
shadowCoord = fadeShadow(shadowCoord, light{i}_shadowCascadeDistances);
// ----- sample the shadow -----
return getShadowVSM16(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, 5.54);
return getShadowVSM32(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, 15.0);
vec2 shadowSearchArea = vec2(length(light{i}_halfWidth), length(light{i}_halfHeight)) * light{i}_shadowSearchArea;
return getShadowPCSS(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, light{i}_cameraParams, shadowSearchArea, lightDirW);
return getShadowPCSS(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, light{i}_cameraParams, light{i}_softShadowParams, lightDirW);
return getShadowPCF1x1(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams);
return getShadowPCF3x3(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams);
return getShadowPCF5x5(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams);
return getShadowSpotVSM16(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, 5.54, lightDirW);
return getShadowSpotVSM32(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, 15.0, lightDirW);
vec2 shadowSearchArea = vec2(length(light{i}_halfWidth), length(light{i}_halfHeight)) * light{i}_shadowSearchArea;
vec2 shadowSearchArea = vec2(light{i}_shadowSearchArea);
return getShadowSpotPCSS(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, light{i}_cameraParams, shadowSearchArea, lightDirW);
return getShadowSpotPCF1x1(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams);
return getShadowSpotPCF3x3(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams);
return getShadowSpotPCF5x5(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams);
vec2 shadowSearchArea = vec2(length(light{i}_halfWidth), length(light{i}_halfHeight)) * light{i}_shadowSearchArea;
vec2 shadowSearchArea = vec2(light{i}_shadowSearchArea);
return getShadowOmniPCSS(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, light{i}_cameraParams, shadowSearchArea, lightDirW);
return getShadowOmniPCF1x1(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, lightDirW);
return getShadowOmniPCF3x3(SHADOWMAP_PASS(light{i}_shadowMap), shadowCoord, light{i}_shadowParams, lightDirW);
}
`;
export { lightFunctionShadowPS as default };