shadowmap_pars_fragment.glsl 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. #ifdef USE_SHADOWMAP
  2. #if NUM_DIR_LIGHTS > 0
  3. uniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];
  4. varying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];
  5. #endif
  6. #if NUM_SPOT_LIGHTS > 0
  7. uniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];
  8. varying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];
  9. #endif
  10. #if NUM_POINT_LIGHTS > 0
  11. uniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];
  12. varying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];
  13. #endif
  14. float unpackDepth( const in vec4 rgba_depth ) {
  15. const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );
  16. return dot( rgba_depth, bit_shift );
  17. }
  18. float texture2DCompare( sampler2D depths, vec2 uv, float compare ) {
  19. return step( compare, unpackDepth( texture2D( depths, uv ) ) );
  20. }
  21. float texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {
  22. const vec2 offset = vec2( 0.0, 1.0 );
  23. vec2 texelSize = vec2( 1.0 ) / size;
  24. vec2 centroidUV = floor( uv * size + 0.5 ) / size;
  25. float lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );
  26. float lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );
  27. float rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );
  28. float rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );
  29. vec2 f = fract( uv * size + 0.5 );
  30. float a = mix( lb, lt, f.y );
  31. float b = mix( rb, rt, f.y );
  32. float c = mix( a, b, f.x );
  33. return c;
  34. }
  35. float getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {
  36. shadowCoord.xyz /= shadowCoord.w;
  37. shadowCoord.z += shadowBias;
  38. // if ( something && something ) breaks ATI OpenGL shader compiler
  39. // if ( all( something, something ) ) using this instead
  40. bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
  41. bool inFrustum = all( inFrustumVec );
  42. bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );
  43. bool frustumTest = all( frustumTestVec );
  44. if ( frustumTest ) {
  45. #if defined( SHADOWMAP_TYPE_PCF )
  46. vec2 texelSize = vec2( 1.0 ) / shadowMapSize;
  47. float dx0 = - texelSize.x * shadowRadius;
  48. float dy0 = - texelSize.y * shadowRadius;
  49. float dx1 = + texelSize.x * shadowRadius;
  50. float dy1 = + texelSize.y * shadowRadius;
  51. return (
  52. texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +
  53. texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +
  54. texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +
  55. texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +
  56. texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +
  57. texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +
  58. texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +
  59. texture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +
  60. texture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )
  61. ) * ( 1.0 / 9.0 );
  62. #elif defined( SHADOWMAP_TYPE_PCF_SOFT )
  63. vec2 texelSize = vec2( 1.0 ) / shadowMapSize;
  64. float dx0 = - texelSize.x * shadowRadius;
  65. float dy0 = - texelSize.y * shadowRadius;
  66. float dx1 = + texelSize.x * shadowRadius;
  67. float dy1 = + texelSize.y * shadowRadius;
  68. return (
  69. texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +
  70. texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +
  71. texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +
  72. texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +
  73. texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +
  74. texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +
  75. texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +
  76. texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +
  77. texture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )
  78. ) * ( 1.0 / 9.0 );
  79. #else // no percentage-closer filtering:
  80. return texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );
  81. #endif
  82. }
  83. return 1.0;
  84. }
  85. // cubeToUV() maps a 3D direction vector suitable for cube texture mapping to a 2D
  86. // vector suitable for 2D texture mapping. This code uses the following layout for the
  87. // 2D texture:
  88. //
  89. // xzXZ
  90. // y Y
  91. //
  92. // Y - Positive y direction
  93. // y - Negative y direction
  94. // X - Positive x direction
  95. // x - Negative x direction
  96. // Z - Positive z direction
  97. // z - Negative z direction
  98. //
  99. // Source and test bed:
  100. // https://gist.github.com/tschw/da10c43c467ce8afd0c4
  101. vec2 cubeToUV( vec3 v, float texelSizeY ) {
  102. // Number of texels to avoid at the edge of each square
  103. vec3 absV = abs( v );
  104. // Intersect unit cube
  105. float scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );
  106. absV *= scaleToCube;
  107. // Apply scale to avoid seams
  108. // two texels less per square (one texel will do for NEAREST)
  109. v *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );
  110. // Unwrap
  111. // space: -1 ... 1 range for each square
  112. //
  113. // #X## dim := ( 4 , 2 )
  114. // # # center := ( 1 , 1 )
  115. vec2 planar = v.xy;
  116. float almostATexel = 1.5 * texelSizeY;
  117. float almostOne = 1.0 - almostATexel;
  118. if ( absV.z >= almostOne ) {
  119. if ( v.z > 0.0 )
  120. planar.x = 4.0 - v.x;
  121. } else if ( absV.x >= almostOne ) {
  122. float signX = sign( v.x );
  123. planar.x = v.z * signX + 2.0 * signX;
  124. } else if ( absV.y >= almostOne ) {
  125. float signY = sign( v.y );
  126. planar.x = v.x + 2.0 * signY + 2.0;
  127. planar.y = v.z * signY - 2.0;
  128. }
  129. // Transform to UV space
  130. // scale := 0.5 / dim
  131. // translate := ( center + 0.5 ) / dim
  132. return vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );
  133. }
  134. float getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {
  135. vec2 texelSize = vec2( 1.0 ) / shadowMapSize;
  136. // for point lights, the uniform @vShadowCoord is re-purposed to hold
  137. // the distance from the light to the world-space position of the fragment.
  138. vec3 lightToPosition = shadowCoord.xyz;
  139. // bd3D = base direction 3D
  140. vec3 bd3D = normalize( lightToPosition );
  141. // dp = distance from light to fragment position
  142. float dp = ( length( lightToPosition ) - shadowBias ) / 1000.0;
  143. #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )
  144. vec2 offset = vec2( - 1, 1 ) * shadowRadius * 2.0 * texelSize.y;
  145. return (
  146. texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +
  147. texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp ) +
  148. texture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +
  149. texture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp )
  150. ) * ( 1.0 / 4.0 );
  151. #else // no percentage-closer filtering
  152. return texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );
  153. #endif
  154. }
  155. #endif