|
@@ -1,306 +1,266 @@
|
|
|
#ifdef USE_SHADOWMAP
|
|
|
|
|
|
- #ifdef SHADOWMAP_DEBUG
|
|
|
+ vec3 shadowMask = vec3( 1.0 );
|
|
|
|
|
|
- vec3 frustumColors[3];
|
|
|
- frustumColors[0] = vec3( 1.0, 0.5, 0.0 );
|
|
|
- frustumColors[1] = vec3( 0.0, 1.0, 0.8 );
|
|
|
- frustumColors[2] = vec3( 0.0, 0.5, 1.0 );
|
|
|
-
|
|
|
- #endif
|
|
|
+ for ( int i = 0; i < MAX_SHADOWS; i ++ ) {
|
|
|
+
|
|
|
+ float texelSizeY = 1.0 / shadowMapSize[ i ].y;
|
|
|
|
|
|
- float fDepth;
|
|
|
- vec3 shadowColor = vec3( 1.0 );
|
|
|
+ float shadow = 0.0;
|
|
|
|
|
|
- for( int i = 0; i < MAX_SHADOWS; i ++ ) {
|
|
|
+#if defined( POINT_LIGHT_SHADOWS )
|
|
|
|
|
|
// to save on uniform space, we use the sign of @shadowDarkness[ i ] to determine
|
|
|
// whether or not this light is a point light ( shadowDarkness[ i ] < 0 == point light)
|
|
|
- bool isPointLight = shadowDarkness[ i ] < 0.0;
|
|
|
-
|
|
|
- // get the real shadow darkness
|
|
|
- float realShadowDarkness = abs( shadowDarkness[ i ] );
|
|
|
-
|
|
|
- // for point lights, the uniform @vShadowCoord is re-purposed to hold
|
|
|
- // the distance from the light to the world-space position of the fragment.
|
|
|
- vec3 lightToPosition = vShadowCoord[ i ].xyz;
|
|
|
-
|
|
|
- float texelSizeX = 1.0 / shadowMapSize[ i ].x;
|
|
|
- float texelSizeY = 1.0 / shadowMapSize[ i ].y;
|
|
|
+ bool isPointLight = shadowDarkness[ i ] < 0.0;
|
|
|
|
|
|
- vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;
|
|
|
- float shadow = 0.0;
|
|
|
+ if ( isPointLight ) {
|
|
|
|
|
|
- // if ( something && something ) breaks ATI OpenGL shader compiler
|
|
|
- // if ( all( something, something ) ) using this instead
|
|
|
+ // get the real shadow darkness
|
|
|
+ float realShadowDarkness = abs( shadowDarkness[ i ] );
|
|
|
|
|
|
- bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
|
|
|
- bool inFrustum = all( inFrustumVec );
|
|
|
+ // for point lights, the uniform @vShadowCoord is re-purposed to hold
|
|
|
+ // the distance from the light to the world-space position of the fragment.
|
|
|
+ vec3 lightToPosition = vShadowCoord[ i ].xyz;
|
|
|
|
|
|
- bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );
|
|
|
+ #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )
|
|
|
|
|
|
- bool frustumTest = all( frustumTestVec );
|
|
|
+ // bd3D = base direction 3D
|
|
|
+ vec3 bd3D = normalize( lightToPosition );
|
|
|
+ // dp = distance from light to fragment position
|
|
|
+ float dp = length( lightToPosition );
|
|
|
|
|
|
- if ( frustumTest || isPointLight ) {
|
|
|
+ // base measurement
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
|
|
|
- #if defined( SHADOWMAP_TYPE_PCF )
|
|
|
+ // Dr = disk radius
|
|
|
|
|
|
- #if defined(POINT_LIGHT_SHADOWS)
|
|
|
-
|
|
|
- if( isPointLight ) {
|
|
|
-
|
|
|
- float cubeTexelSize = 1.0 / ( shadowMapSize[ i ].x * 0.25 );
|
|
|
- vec3 baseDirection3D = normalize( lightToPosition );
|
|
|
- vec2 baseDirection2D = cubeToUV( baseDirection3D, texelSizeY );
|
|
|
-
|
|
|
- initGridSamplingDisk();
|
|
|
-
|
|
|
- float diskRadius = 1.25;
|
|
|
- float numSamples = 1.0;
|
|
|
- shadow = 0.0;
|
|
|
-
|
|
|
- vec3 baseDirection = normalize( lightToPosition );
|
|
|
- float curDistance = length( lightToPosition );
|
|
|
-
|
|
|
- float dist = unpack1K( texture2D( shadowMap[ i ], baseDirection2D ) ) + 0.1;
|
|
|
- if ( curDistance >= dist )
|
|
|
- shadow += 1.0;
|
|
|
-
|
|
|
- // evaluate each sampling direction
|
|
|
- for( int s = 0; s < 20; s++ ) {
|
|
|
-
|
|
|
- vec3 offset = gridSamplingDisk[ s ] * diskRadius * cubeTexelSize;
|
|
|
- vec3 adjustedBaseDirection3D = baseDirection3D + offset;
|
|
|
- vec2 adjustedBaseDirection2D = cubeToUV( adjustedBaseDirection3D, texelSizeY );
|
|
|
- dist = unpack1K( texture2D( shadowMap[ i ], adjustedBaseDirection2D ) ) + shadowBias[ i ];
|
|
|
- if ( curDistance >= dist )
|
|
|
- shadow += 1.0;
|
|
|
- numSamples += 1.0;
|
|
|
+ #if defined( SHADOWMAP_TYPE_PCF )
|
|
|
+ const float Dr = 1.25;
|
|
|
+ #elif defined( SHADOWMAP_TYPE_PCF_SOFT )
|
|
|
+ const float Dr = 2.25;
|
|
|
+ #endif
|
|
|
|
|
|
- }
|
|
|
+ // os = offset scale
|
|
|
+ float os = Dr * 2.0 * texelSizeY;
|
|
|
|
|
|
- shadow /= numSamples;
|
|
|
+ const vec3 Gsd = vec3( - 1, 0, 1 );
|
|
|
|
|
|
- } else {
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzz * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxz * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxz * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzz * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzx * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxx * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxx * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzx * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzy * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxy * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
|
|
|
- #endif
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxy * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzy * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zyz * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xyz * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zyx * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xyx * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yzz * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yxz * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yxx * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yzx * os, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
|
|
|
- // Percentage-close filtering
|
|
|
- // (9 pixel kernel)
|
|
|
- // http://fabiensanglard.net/shadowmappingPCF/
|
|
|
-
|
|
|
- /*
|
|
|
- // nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
|
|
|
- // must enroll loop manually
|
|
|
- for ( float y = -1.25; y <= 1.25; y += 1.25 )
|
|
|
- for ( float x = -1.25; x <= 1.25; x += 1.25 ) {
|
|
|
- vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );
|
|
|
- // doesn't seem to produce any noticeable visual difference compared to simple texture2D lookup
|
|
|
- //vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );
|
|
|
- float fDepth = unpackDepth( rgbaDepth );
|
|
|
- if ( fDepth < shadowCoord.z )
|
|
|
- shadow += 1.0;
|
|
|
- }
|
|
|
- shadow /= 9.0;
|
|
|
- */
|
|
|
+ shadow *= realShadowDarkness * ( 1.0 / 21.0 );
|
|
|
|
|
|
- shadowCoord.z += shadowBias[ i ];
|
|
|
+ #else // no percentage-closer filtering:
|
|
|
|
|
|
- const float shadowDelta = 1.0 / 9.0;
|
|
|
+ vec3 bd3D = normalize( lightToPosition );
|
|
|
+ float dp = length( lightToPosition );
|
|
|
|
|
|
- float xPixelOffset = texelSizeX;
|
|
|
- float yPixelOffset = texelSizeY;
|
|
|
+ adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
|
|
|
|
|
|
- float dx0 = -1.25 * xPixelOffset;
|
|
|
- float dy0 = -1.25 * yPixelOffset;
|
|
|
- float dx1 = 1.25 * xPixelOffset;
|
|
|
- float dy1 = 1.25 * yPixelOffset;
|
|
|
+ shadow *= realShadowDarkness;
|
|
|
|
|
|
- fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
|
|
|
- if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
|
|
|
+ #endif
|
|
|
|
|
|
- fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
|
|
|
- if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
|
|
|
+ } else {
|
|
|
|
|
|
- fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
|
|
|
- if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
|
|
|
+#endif // POINT_LIGHT_SHADOWS
|
|
|
|
|
|
- fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
|
|
|
- if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
|
|
|
+ float texelSizeX = 1.0 / shadowMapSize[ i ].x;
|
|
|
|
|
|
- fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
|
|
|
- if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
|
|
|
+ vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;
|
|
|
|
|
|
- fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
|
|
|
- if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
|
|
|
+ // if ( something && something ) breaks ATI OpenGL shader compiler
|
|
|
+ // if ( all( something, something ) ) using this instead
|
|
|
|
|
|
- fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
|
|
|
- if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
|
|
|
+ bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
|
|
|
+ bool inFrustum = all( inFrustumVec );
|
|
|
|
|
|
- fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
|
|
|
- if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
|
|
|
+ bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );
|
|
|
|
|
|
- fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
|
|
|
- if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
|
|
|
+ bool frustumTest = all( frustumTestVec );
|
|
|
|
|
|
- #if defined(POINT_LIGHT_SHADOWS)
|
|
|
+ if ( frustumTest ) {
|
|
|
|
|
|
+ #if defined( SHADOWMAP_TYPE_PCF )
|
|
|
+
|
|
|
+ // Percentage-close filtering
|
|
|
+ // (9 pixel kernel)
|
|
|
+ // http://fabiensanglard.net/shadowmappingPCF/
|
|
|
+
|
|
|
+ /*
|
|
|
+ // nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
|
|
|
+ // must enroll loop manually
|
|
|
+ for ( float y = -1.25; y <= 1.25; y += 1.25 )
|
|
|
+ for ( float x = -1.25; x <= 1.25; x += 1.25 ) {
|
|
|
+ vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );
|
|
|
+ // doesn't seem to produce any noticeable visual difference compared to simple texture2D lookup
|
|
|
+ //vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );
|
|
|
+ float fDepth = unpackDepth( rgbaDepth );
|
|
|
+ if ( fDepth < shadowCoord.z )
|
|
|
+ shadow += 1.0;
|
|
|
}
|
|
|
+ shadow /= 9.0;
|
|
|
+ */
|
|
|
|
|
|
- #endif
|
|
|
-
|
|
|
- shadowColor = shadowColor * vec3( ( 1.0 - realShadowDarkness * shadow ) );
|
|
|
+ shadowCoord.z += shadowBias[ i ];
|
|
|
|
|
|
- #elif defined( SHADOWMAP_TYPE_PCF_SOFT )
|
|
|
+ const float ShadowDelta = 1.0 / 9.0;
|
|
|
|
|
|
- #if defined(POINT_LIGHT_SHADOWS)
|
|
|
+ float xPixelOffset = texelSizeX;
|
|
|
+ float yPixelOffset = texelSizeY;
|
|
|
|
|
|
- if( isPointLight ) {
|
|
|
+ float dx0 = - 1.25 * xPixelOffset;
|
|
|
+ float dy0 = - 1.25 * yPixelOffset;
|
|
|
+ float dx1 = 1.25 * xPixelOffset;
|
|
|
+ float dy1 = 1.25 * yPixelOffset;
|
|
|
|
|
|
- float cubeTexelSize = 1.0 / ( shadowMapSize[ i ].x * 0.25 );
|
|
|
- vec3 baseDirection3D = normalize( lightToPosition );
|
|
|
- vec2 baseDirection2D = cubeToUV( baseDirection3D, texelSizeY );
|
|
|
+ float fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
|
|
|
+ if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
|
|
|
|
|
|
- initGridSamplingDisk();
|
|
|
+ fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
|
|
|
+ if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
|
|
|
|
|
|
- float diskRadius = 2.25;
|
|
|
- float numSamples = 1.0;
|
|
|
- shadow = 0.0;
|
|
|
+ fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
|
|
|
+ if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
|
|
|
|
|
|
- vec3 baseDirection = normalize( lightToPosition );
|
|
|
- float curDistance = length( lightToPosition );
|
|
|
+ fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
|
|
|
+ if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
|
|
|
|
|
|
- float dist = unpack1K( texture2D( shadowMap[ i ], baseDirection2D ) ) + 0.1;
|
|
|
- if ( curDistance >= dist )
|
|
|
- shadow += 1.0;
|
|
|
-
|
|
|
- // evaluate each sampling direction
|
|
|
- for( int s = 0; s < 20; s++ ) {
|
|
|
-
|
|
|
- vec3 offset = gridSamplingDisk[ s ] * diskRadius * cubeTexelSize;
|
|
|
- vec3 adjustedBaseDirection3D = baseDirection3D + offset;
|
|
|
- vec2 adjustedBaseDirection2D = cubeToUV( adjustedBaseDirection3D, texelSizeY );
|
|
|
- dist = unpack1K( texture2D( shadowMap[ i ], adjustedBaseDirection2D ) ) + shadowBias[ i ];
|
|
|
- if ( curDistance >= dist )
|
|
|
- shadow += 1.0;
|
|
|
- numSamples += 1.0;
|
|
|
+ fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
|
|
|
+ if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
|
|
|
|
|
|
- }
|
|
|
+ fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
|
|
|
+ if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
|
|
|
|
|
|
- shadow /= numSamples;
|
|
|
+ fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
|
|
|
+ if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
|
|
|
|
|
|
- } else {
|
|
|
+ fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
|
|
|
+ if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
|
|
|
|
|
|
- #endif
|
|
|
+ fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
|
|
|
+ if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
|
|
|
|
|
|
- // Percentage-close filtering
|
|
|
- // (9 pixel kernel)
|
|
|
- // http://fabiensanglard.net/shadowmappingPCF/
|
|
|
+ shadow *= shadowDarkness[ i ];
|
|
|
|
|
|
- shadowCoord.z += shadowBias[ i ];
|
|
|
+ #elif defined( SHADOWMAP_TYPE_PCF_SOFT )
|
|
|
|
|
|
- float xPixelOffset = texelSizeX;
|
|
|
- float yPixelOffset = texelSizeY;
|
|
|
+ // Percentage-close filtering
|
|
|
+ // (9 pixel kernel)
|
|
|
+ // http://fabiensanglard.net/shadowmappingPCF/
|
|
|
|
|
|
- float dx0 = -1.0 * xPixelOffset;
|
|
|
- float dy0 = -1.0 * yPixelOffset;
|
|
|
- float dx1 = 1.0 * xPixelOffset;
|
|
|
- float dy1 = 1.0 * yPixelOffset;
|
|
|
+ shadowCoord.z += shadowBias[ i ];
|
|
|
|
|
|
- mat3 shadowKernel;
|
|
|
- mat3 depthKernel;
|
|
|
+ float xPixelOffset = texelSizeX;
|
|
|
+ float yPixelOffset = texelSizeY;
|
|
|
|
|
|
- depthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
|
|
|
- depthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
|
|
|
- depthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
|
|
|
- depthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
|
|
|
- depthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
|
|
|
- depthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
|
|
|
- depthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
|
|
|
- depthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
|
|
|
- depthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
|
|
|
+ float dx0 = - 1.0 * xPixelOffset;
|
|
|
+ float dy0 = - 1.0 * yPixelOffset;
|
|
|
+ float dx1 = 1.0 * xPixelOffset;
|
|
|
+ float dy1 = 1.0 * yPixelOffset;
|
|
|
|
|
|
- vec3 shadowZ = vec3( shadowCoord.z );
|
|
|
- shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));
|
|
|
- shadowKernel[0] *= vec3(0.25);
|
|
|
+ mat3 shadowKernel;
|
|
|
+ mat3 depthKernel;
|
|
|
|
|
|
- shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));
|
|
|
- shadowKernel[1] *= vec3(0.25);
|
|
|
+ depthKernel[ 0 ][ 0 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
|
|
|
+ depthKernel[ 0 ][ 1 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
|
|
|
+ depthKernel[ 0 ][ 2 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
|
|
|
+ depthKernel[ 1 ][ 0 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
|
|
|
+ depthKernel[ 1 ][ 1 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
|
|
|
+ depthKernel[ 1 ][ 2 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
|
|
|
+ depthKernel[ 2 ][ 0 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
|
|
|
+ depthKernel[ 2 ][ 1 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
|
|
|
+ depthKernel[ 2 ][ 2 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
|
|
|
|
|
|
- shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));
|
|
|
- shadowKernel[2] *= vec3(0.25);
|
|
|
+ vec3 shadowZ = vec3( shadowCoord.z );
|
|
|
+ shadowKernel[ 0 ] = vec3( lessThan( depthKernel[ 0 ], shadowZ ) );
|
|
|
+ shadowKernel[ 0 ] *= vec3( 0.25 );
|
|
|
|
|
|
- vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );
|
|
|
+ shadowKernel[ 1 ] = vec3( lessThan( depthKernel[ 1 ], shadowZ ) );
|
|
|
+ shadowKernel[ 1 ] *= vec3( 0.25 );
|
|
|
|
|
|
- shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );
|
|
|
- shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );
|
|
|
+ shadowKernel[ 2 ] = vec3( lessThan( depthKernel[ 2 ], shadowZ ) );
|
|
|
+ shadowKernel[ 2 ] *= vec3( 0.25 );
|
|
|
|
|
|
- vec4 shadowValues;
|
|
|
- shadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y );
|
|
|
- shadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y );
|
|
|
- shadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y );
|
|
|
- shadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y );
|
|
|
+ vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[ i ].xy );
|
|
|
|
|
|
- shadow = dot( shadowValues, vec4( 1.0 ) );
|
|
|
+ shadowKernel[ 0 ] = mix( shadowKernel[ 1 ], shadowKernel[ 0 ], fractionalCoord.x );
|
|
|
+ shadowKernel[ 1 ] = mix( shadowKernel[ 2 ], shadowKernel[ 1 ], fractionalCoord.x );
|
|
|
|
|
|
- #if defined(POINT_LIGHT_SHADOWS)
|
|
|
-
|
|
|
- }
|
|
|
+ vec4 shadowValues;
|
|
|
+ shadowValues.x = mix( shadowKernel[ 0 ][ 1 ], shadowKernel[ 0 ][ 0 ], fractionalCoord.y );
|
|
|
+ shadowValues.y = mix( shadowKernel[ 0 ][ 2 ], shadowKernel[ 0 ][ 1 ], fractionalCoord.y );
|
|
|
+ shadowValues.z = mix( shadowKernel[ 1 ][ 1 ], shadowKernel[ 1 ][ 0 ], fractionalCoord.y );
|
|
|
+ shadowValues.w = mix( shadowKernel[ 1 ][ 2 ], shadowKernel[ 1 ][ 1 ], fractionalCoord.y );
|
|
|
|
|
|
- #endif
|
|
|
+ shadow = dot( shadowValues, vec4( 1.0 ) ) * shadowDarkness[ i ];
|
|
|
|
|
|
- shadowColor = shadowColor * vec3( ( 1.0 - realShadowDarkness * shadow ) );
|
|
|
+ #else // no percentage-closer filtering:
|
|
|
+
|
|
|
+ shadowCoord.z += shadowBias[ i ];
|
|
|
|
|
|
- #else
|
|
|
+ vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
|
|
|
+ float fDepth = unpackDepth( rgbaDepth );
|
|
|
|
|
|
- #if defined(POINT_LIGHT_SHADOWS)
|
|
|
+ if ( fDepth < shadowCoord.z )
|
|
|
+ shadow = shadowDarkness[ i ];
|
|
|
|
|
|
- if( isPointLight ) {
|
|
|
+ #endif
|
|
|
|
|
|
- vec3 baseDirection3D = normalize( lightToPosition );
|
|
|
- vec2 baseDirection2D = cubeToUV( baseDirection3D, texelSizeY );
|
|
|
- vec4 data = texture2D( shadowMap[ i ], baseDirection2D );
|
|
|
- float dist = unpack1K( data ) + shadowBias[ i ];
|
|
|
- if ( length( lightToPosition ) >= dist)
|
|
|
- shadowColor = shadowColor * vec3( 1.0 - realShadowDarkness );
|
|
|
+ }
|
|
|
|
|
|
- } else {
|
|
|
+#ifdef SHADOWMAP_DEBUG
|
|
|
|
|
|
- #endif
|
|
|
- shadowCoord.z += shadowBias[ i ];
|
|
|
+ if ( inFrustum ) {
|
|
|
|
|
|
- vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
|
|
|
- float fDepth = unpackDepth( rgbaDepth );
|
|
|
+ if ( i == 0 ) {
|
|
|
|
|
|
- if ( fDepth < shadowCoord.z )
|
|
|
+ outgoingLight *= vec3( 1.0, 0.5, 0.0 );
|
|
|
|
|
|
- // spot with multiple shadows is darker
|
|
|
+ } else if ( i == 1 ) {
|
|
|
|
|
|
- shadowColor = shadowColor * vec3( 1.0 - realShadowDarkness );
|
|
|
+ outgoingLight *= vec3( 0.0, 1.0, 0.8 );
|
|
|
|
|
|
- // spot with multiple shadows has the same color as single shadow spot
|
|
|
+ } else {
|
|
|
|
|
|
- // shadowColor = min( shadowColor, vec3( realShadowDarkness ) );
|
|
|
+ outgoingLight *= vec3( 0.0, 0.5, 1.0 );
|
|
|
|
|
|
- #if defined(POINT_LIGHT_SHADOWS)
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- #endif
|
|
|
+#endif
|
|
|
|
|
|
- #endif
|
|
|
+#if defined( POINT_LIGHT_SHADOWS )
|
|
|
|
|
|
}
|
|
|
|
|
|
+#endif
|
|
|
|
|
|
- #ifdef SHADOWMAP_DEBUG
|
|
|
-
|
|
|
- if ( inFrustum ) outgoingLight *= frustumColors[ i ];
|
|
|
-
|
|
|
- #endif
|
|
|
+ shadowMask = shadowMask * vec3( 1.0 - shadow );
|
|
|
|
|
|
}
|
|
|
|
|
|
- outgoingLight = outgoingLight * shadowColor;
|
|
|
+ outgoingLight = outgoingLight * shadowMask;
|
|
|
|
|
|
#endif
|