123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- /**
- * Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Ludovic Autin <ludovic.autin@gmail.com>
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
- export const shadows_frag = `
- precision highp float;
- precision highp int;
- precision highp sampler2D;
- #include common
- uniform sampler2D tDepth;
- uniform vec2 uTexSize;
- uniform vec4 uBounds;
- uniform float uNear;
- uniform float uFar;
- #if dLightCount != 0
- uniform vec3 uLightDirection[dLightCount];
- uniform vec3 uLightColor[dLightCount];
- #endif
- uniform mat4 uProjection;
- uniform mat4 uInvProjection;
- uniform float uMaxDistance;
- uniform float uTolerance;
- uniform float uBias;
- bool isBackground(const in float depth) {
- return depth == 1.0;
- }
- bool outsideBounds(const in vec2 p) {
- return p.x < uBounds.x || p.y < uBounds.y || p.x > uBounds.z || p.y > uBounds.w;
- }
- float getViewZ(const in float depth) {
- #if dOrthographic == 1
- return orthographicDepthToViewZ(depth, uNear, uFar);
- #else
- return perspectiveDepthToViewZ(depth, uNear, uFar);
- #endif
- }
- float getDepth(const in vec2 coords) {
- #ifdef depthTextureSupport
- return texture2D(tDepth, coords).r;
- #else
- return unpackRGBAToDepth(texture2D(tDepth, coords));
- #endif
- }
- float screenFade(const in vec2 coords) {
- vec2 c = (coords - uBounds.xy) / (uBounds.zw - uBounds.xy);
- vec2 fade = max(12.0 * abs(c - 0.5) - 5.0, vec2(0.0));
- return saturate(1.0 - dot(fade, fade));
- }
- // based on https://panoskarabelas.com/posts/screen_space_shadows/
- float screenSpaceShadow(const in vec3 position, const in vec3 lightDirection, const in float stepLength) {
- // Ray position and direction (in view-space)
- vec3 rayPos = position;
- vec3 rayDir = -lightDirection;
- // Compute ray step
- vec3 rayStep = rayDir * stepLength;
- // Ray march towards the light
- float occlusion = 0.0;
- vec4 rayCoords = vec4(0.0);
- for (int i = 0; i < dSteps; ++i) {
- // Step the ray
- rayPos += rayStep;
- rayCoords = uProjection * vec4(rayPos, 1.0);
- rayCoords.xyz = (rayCoords.xyz / rayCoords.w) * 0.5 + 0.5;
- if (outsideBounds(rayCoords.xy))
- return 1.0;
- // Compute the difference between the ray's and the camera's depth
- float depth = getDepth(rayCoords.xy);
- float viewZ = getViewZ(depth);
- float zDelta = rayPos.z - viewZ;
- if (zDelta < uTolerance) {
- occlusion = 1.0;
- // Fade out as we approach the edges of the screen
- occlusion *= screenFade(rayCoords.xy);
- break;
- }
- }
- return 1.0 - (uBias * occlusion);
- }
- void main(void) {
- vec2 invTexSize = 1.0 / uTexSize;
- vec2 selfCoords = gl_FragCoord.xy * invTexSize;
- float selfDepth = getDepth(selfCoords);
- if (isBackground(selfDepth)) {
- gl_FragColor = vec4(0.0);
- return;
- }
- vec3 selfViewPos = screenSpaceToViewSpace(vec3(selfCoords, selfDepth), uInvProjection);
- float stepLength = uMaxDistance / float(dSteps);
- float o = 1.0;
- #if dLightCount != 0
- float sh[dLightCount];
- #pragma unroll_loop_start
- for (int i = 0; i < dLightCount; ++i) {
- sh[i] = screenSpaceShadow(selfViewPos, uLightDirection[i], stepLength);
- o = min(o, sh[i]);
- }
- #pragma unroll_loop_end
- #endif
- gl_FragColor = vec4(o);
- }
- `;
|