UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

3 lines (2 loc) 4.09 kB
declare const _default: "\n\n// ------ VSM Shared ------\n\nfn linstep(a: f32, b: f32, v: f32) -> f32 {\n // WGSL saturate -> clamp\n return clamp((v - a) / (b - a), 0.0, 1.0);\n}\n\nfn reduceLightBleeding(pMax: f32, amount: f32) -> f32 {\n // Remove the [0, amount] tail and linearly rescale (amount, 1].\n return linstep(amount, 1.0, pMax);\n}\n\nfn chebyshevUpperBound(moments: vec2f, mean: f32, minVariance: f32, lightBleedingReduction: f32) -> f32 {\n // Compute variance\n var variance: f32 = moments.y - (moments.x * moments.x);\n variance = max(variance, minVariance);\n\n // Compute probabilistic upper bound\n let d: f32 = mean - moments.x;\n var pMax: f32 = variance / (variance + (d * d));\n\n pMax = reduceLightBleeding(pMax, lightBleedingReduction);\n\n // One-tailed Chebyshev\n return select(pMax, 1.0, mean <= moments.x);\n}\n\nfn calculateEVSM(moments_in: vec3f, Z_in: f32, vsmBias: f32, exponent: f32) -> f32 {\n let Z: f32 = 2.0 * Z_in - 1.0;\n let warpedDepth: f32 = exp(exponent * Z);\n\n let moments: vec2f = moments_in.xy + vec2f(warpedDepth, warpedDepth*warpedDepth) * (1.0 - moments_in.z);\n\n let VSMBias: f32 = vsmBias;//0.01 * 0.25;\n let depthScale: f32 = VSMBias * exponent * warpedDepth;\n let minVariance1: f32 = depthScale * depthScale;\n return chebyshevUpperBound(moments, warpedDepth, minVariance1, 0.1);\n}\n// ------ VSM 16 ------\n\nfn VSM16(tex: texture_2d<f32>, texSampler: sampler, texCoords: vec2f, resolution: f32, Z: f32, vsmBias: f32, exponent: f32) -> f32 {\n let moments: vec3f = textureSampleLevel(tex, texSampler, texCoords, 0.0).xyz;\n return calculateEVSM(moments, Z, vsmBias, exponent);\n}\n\nfn getShadowVSM16(shadowMap: texture_2d<f32>, shadowMapSampler: sampler, shadowCoord: vec3f, shadowParams: vec4f, exponent: f32) -> f32 {\n return VSM16(shadowMap, shadowMapSampler, shadowCoord.xy, shadowParams.x, shadowCoord.z, shadowParams.y, exponent);\n}\n\nfn getShadowSpotVSM16(shadowMap: texture_2d<f32>, shadowMapSampler: sampler, shadowCoord: vec3f, shadowParams: vec4f, exponent: f32, lightDir: vec3f) -> f32 {\n let Z: f32 = length(lightDir) * shadowParams.w + shadowParams.z;\n return VSM16(shadowMap, shadowMapSampler, shadowCoord.xy, shadowParams.x, Z, shadowParams.y, exponent);\n}\n\n// ------ VSM 32 ------\n\nfn VSM32(tex: texture_2d<f32>, texSampler: sampler, texCoords_in: vec2f, resolution: f32, Z: f32, vsmBias: f32, exponent: f32) -> f32 {\n\n #ifdef CAPS_TEXTURE_FLOAT_FILTERABLE\n var moments: vec3f = textureSampleLevel(tex, texSampler, texCoords_in, 0.0).xyz;\n #else\n // manual bilinear filtering\n var pixelSize : f32 = 1.0 / resolution;\n let texCoords: vec2f = texCoords_in - vec2f(pixelSize);\n let s00: vec3f = textureSampleLevel(tex, texSampler, texCoords, 0.0).xyz;\n let s10: vec3f = textureSampleLevel(tex, texSampler, texCoords + vec2f(pixelSize, 0.0), 0.0).xyz;\n let s01: vec3f = textureSampleLevel(tex, texSampler, texCoords + vec2f(0.0, pixelSize), 0.0).xyz;\n let s11: vec3f = textureSampleLevel(tex, texSampler, texCoords + vec2f(pixelSize), 0.0).xyz;\n let fr: vec2f = fract(texCoords * resolution);\n let h0: vec3f = mix(s00, s10, fr.x);\n let h1: vec3f = mix(s01, s11, fr.x);\n var moments: vec3f = mix(h0, h1, fr.y);\n #endif\n\n return calculateEVSM(moments, Z, vsmBias, exponent);\n}\n\nfn getShadowVSM32(shadowMap: texture_2d<f32>, shadowMapSampler: sampler, shadowCoord: vec3f, shadowParams: vec4f, exponent: f32) -> f32 {\n return VSM32(shadowMap, shadowMapSampler, shadowCoord.xy, shadowParams.x, shadowCoord.z, shadowParams.y, exponent);\n}\n\nfn getShadowSpotVSM32(shadowMap: texture_2d<f32>, shadowMapSampler: sampler, shadowCoord: vec3f, shadowParams: vec4f, exponent: f32, lightDir: vec3f) -> f32 {\n let Z: f32 = length(lightDir) * shadowParams.w + shadowParams.z;\n return VSM32(shadowMap, shadowMapSampler, shadowCoord.xy, shadowParams.x, Z, shadowParams.y, exponent);\n}\n"; export default _default;