123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- // Shadows
- #ifdef SHADOWS
- float unpack(vec4 color)
- {
- const vec4 bit_shift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);
- return dot(color, bit_shift);
- }
- #if defined(POINTLIGHT0) || defined(POINTLIGHT1) || defined(POINTLIGHT2) || defined(POINTLIGHT3)
- uniform vec2 depthValues;
- float computeShadowCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, float bias)
- {
- vec3 directionToLight = vPositionW - lightPosition;
- float depth = length(directionToLight);
- depth = clamp(depth, 0., 1.0);
- directionToLight = normalize(directionToLight);
- directionToLight.y = - directionToLight.y;
- float shadow = unpack(textureCube(shadowSampler, directionToLight)) + bias;
- if (depth > shadow)
- {
- #ifdef OVERLOADEDSHADOWVALUES
- return mix(1.0, darkness, vOverloadedShadowIntensity.x);
- #else
- return darkness;
- #endif
- }
- return 1.0;
- }
- float computeShadowWithPCFCube(vec3 lightPosition, samplerCube shadowSampler, float mapSize, float bias, float darkness)
- {
- vec3 directionToLight = vPositionW - lightPosition;
- float depth = length(directionToLight);
- depth = (depth - depthValues.x) / (depthValues.y - depthValues.x);
- depth = clamp(depth, 0., 1.0);
- directionToLight = normalize(directionToLight);
- directionToLight.y = -directionToLight.y;
- float visibility = 1.;
- vec3 poissonDisk[4];
- poissonDisk[0] = vec3(-1.0, 1.0, -1.0);
- poissonDisk[1] = vec3(1.0, -1.0, -1.0);
- poissonDisk[2] = vec3(-1.0, -1.0, -1.0);
- poissonDisk[3] = vec3(1.0, -1.0, 1.0);
- // Poisson Sampling
- float biasedDepth = depth - bias;
- if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[0] * mapSize)) < biasedDepth) visibility -= 0.25;
- if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[1] * mapSize)) < biasedDepth) visibility -= 0.25;
- if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[2] * mapSize)) < biasedDepth) visibility -= 0.25;
- if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[3] * mapSize)) < biasedDepth) visibility -= 0.25;
- #ifdef OVERLOADEDSHADOWVALUES
- return min(1.0, mix(1.0, visibility + darkness, vOverloadedShadowIntensity.x));
- #else
- return min(1.0, visibility + darkness);
- #endif
- }
- #endif
- #if defined(SPOTLIGHT0) || defined(SPOTLIGHT1) || defined(SPOTLIGHT2) || defined(SPOTLIGHT3) || defined(DIRLIGHT0) || defined(DIRLIGHT1) || defined(DIRLIGHT2) || defined(DIRLIGHT3)
- float computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler, float darkness, float bias)
- {
- vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
- depth = 0.5 * depth + vec3(0.5);
- vec2 uv = depth.xy;
- if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
- {
- return 1.0;
- }
- float shadow = unpack(texture2D(shadowSampler, uv)) + bias;
- if (depth.z > shadow)
- {
- #ifdef OVERLOADEDSHADOWVALUES
- return mix(1.0, darkness, vOverloadedShadowIntensity.x);
- #else
- return darkness;
- #endif
- }
- return 1.;
- }
- float computeShadowWithPCF(vec4 vPositionFromLight, sampler2D shadowSampler, float mapSize, float bias, float darkness)
- {
- vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
- depth = 0.5 * depth + vec3(0.5);
- vec2 uv = depth.xy;
- if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
- {
- return 1.0;
- }
- float visibility = 1.;
- vec2 poissonDisk[4];
- poissonDisk[0] = vec2(-0.94201624, -0.39906216);
- poissonDisk[1] = vec2(0.94558609, -0.76890725);
- poissonDisk[2] = vec2(-0.094184101, -0.92938870);
- poissonDisk[3] = vec2(0.34495938, 0.29387760);
- // Poisson Sampling
- float biasedDepth = depth.z - bias;
- if (unpack(texture2D(shadowSampler, uv + poissonDisk[0] * mapSize)) < biasedDepth) visibility -= 0.25;
- if (unpack(texture2D(shadowSampler, uv + poissonDisk[1] * mapSize)) < biasedDepth) visibility -= 0.25;
- if (unpack(texture2D(shadowSampler, uv + poissonDisk[2] * mapSize)) < biasedDepth) visibility -= 0.25;
- if (unpack(texture2D(shadowSampler, uv + poissonDisk[3] * mapSize)) < biasedDepth) visibility -= 0.25;
- #ifdef OVERLOADEDSHADOWVALUES
- return min(1.0, mix(1.0, visibility + darkness, vOverloadedShadowIntensity.x));
- #else
- return min(1.0, visibility + darkness);
- #endif
- }
- // Thanks to http://devmaster.net/
- float unpackHalf(vec2 color)
- {
- return color.x + (color.y / 255.0);
- }
- float linstep(float low, float high, float v) {
- return clamp((v - low) / (high - low), 0.0, 1.0);
- }
- float ChebychevInequality(vec2 moments, float compare, float bias)
- {
- float p = smoothstep(compare - bias, compare, moments.x);
- float variance = max(moments.y - moments.x * moments.x, 0.02);
- float d = compare - moments.x;
- float p_max = linstep(0.2, 1.0, variance / (variance + d * d));
- return clamp(max(p, p_max), 0.0, 1.0);
- }
- float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler, float bias, float darkness)
- {
- vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
- depth = 0.5 * depth + vec3(0.5);
- vec2 uv = depth.xy;
- if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0 || depth.z >= 1.0)
- {
- return 1.0;
- }
- vec4 texel = texture2D(shadowSampler, uv);
- vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
- #ifdef OVERLOADEDSHADOWVALUES
- return min(1.0, mix(1.0, 1.0 - ChebychevInequality(moments, depth.z, bias) + darkness, vOverloadedShadowIntensity.x));
- #else
- return min(1.0, 1.0 - ChebychevInequality(moments, depth.z, bias) + darkness);
- #endif
- }
- #endif
- #endif
|