shadowmap_fragment.glsl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #ifdef USE_SHADOWMAP
  2. vec3 shadowMask = vec3( 1.0 );
  3. float shadows[ NUM_SHADOWS ];
  4. for ( int i = 0; i < NUM_SHADOWS; i ++ ) {
  5. float texelSizeY = 1.0 / shadowMapSize[ i ].y;
  6. float shadow = 0.0;
  7. #if defined( POINT_LIGHT_SHADOWS )
  8. // to save on uniform space, we use the sign of @shadowDarkness[ i ] to determine
  9. // whether or not this light is a point light ( shadowDarkness[ i ] < 0 == point light)
  10. bool isPointLight = shadowDarkness[ i ] < 0.0;
  11. if ( isPointLight ) {
  12. // get the real shadow darkness
  13. float realShadowDarkness = abs( shadowDarkness[ i ] );
  14. // for point lights, the uniform @vShadowCoord is re-purposed to hold
  15. // the distance from the light to the world-space position of the fragment.
  16. vec3 lightToPosition = vShadowCoord[ i ].xyz;
  17. #if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )
  18. // bd3D = base direction 3D
  19. vec3 bd3D = normalize( lightToPosition );
  20. // dp = distance from light to fragment position
  21. float dp = length( lightToPosition );
  22. // base measurement
  23. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
  24. // Dr = disk radius
  25. #if defined( SHADOWMAP_TYPE_PCF )
  26. const float Dr = 1.25;
  27. #elif defined( SHADOWMAP_TYPE_PCF_SOFT )
  28. const float Dr = 2.25;
  29. #endif
  30. // os = offset scale
  31. float os = Dr * 2.0 * texelSizeY;
  32. const vec3 Gsd = vec3( - 1, 0, 1 );
  33. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzz * os, texelSizeY ) ), shadowBias[ i ], shadow );
  34. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxz * os, texelSizeY ) ), shadowBias[ i ], shadow );
  35. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxz * os, texelSizeY ) ), shadowBias[ i ], shadow );
  36. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzz * os, texelSizeY ) ), shadowBias[ i ], shadow );
  37. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzx * os, texelSizeY ) ), shadowBias[ i ], shadow );
  38. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxx * os, texelSizeY ) ), shadowBias[ i ], shadow );
  39. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxx * os, texelSizeY ) ), shadowBias[ i ], shadow );
  40. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzx * os, texelSizeY ) ), shadowBias[ i ], shadow );
  41. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zzy * os, texelSizeY ) ), shadowBias[ i ], shadow );
  42. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zxy * os, texelSizeY ) ), shadowBias[ i ], shadow );
  43. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xxy * os, texelSizeY ) ), shadowBias[ i ], shadow );
  44. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xzy * os, texelSizeY ) ), shadowBias[ i ], shadow );
  45. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zyz * os, texelSizeY ) ), shadowBias[ i ], shadow );
  46. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xyz * os, texelSizeY ) ), shadowBias[ i ], shadow );
  47. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.zyx * os, texelSizeY ) ), shadowBias[ i ], shadow );
  48. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.xyx * os, texelSizeY ) ), shadowBias[ i ], shadow );
  49. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yzz * os, texelSizeY ) ), shadowBias[ i ], shadow );
  50. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yxz * os, texelSizeY ) ), shadowBias[ i ], shadow );
  51. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yxx * os, texelSizeY ) ), shadowBias[ i ], shadow );
  52. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + Gsd.yzx * os, texelSizeY ) ), shadowBias[ i ], shadow );
  53. shadow *= realShadowDarkness * ( 1.0 / 21.0 );
  54. #else // no percentage-closer filtering:
  55. vec3 bd3D = normalize( lightToPosition );
  56. float dp = length( lightToPosition );
  57. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
  58. shadow *= realShadowDarkness;
  59. #endif
  60. } else {
  61. #endif // POINT_LIGHT_SHADOWS
  62. float texelSizeX = 1.0 / shadowMapSize[ i ].x;
  63. vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;
  64. // if ( something && something ) breaks ATI OpenGL shader compiler
  65. // if ( all( something, something ) ) using this instead
  66. bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
  67. bool inFrustum = all( inFrustumVec );
  68. bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );
  69. bool frustumTest = all( frustumTestVec );
  70. if ( frustumTest ) {
  71. #if defined( SHADOWMAP_TYPE_PCF )
  72. // Percentage-close filtering
  73. // (9 pixel kernel)
  74. // http://fabiensanglard.net/shadowmappingPCF/
  75. /*
  76. // nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
  77. // must enroll loop manually
  78. for ( float y = -1.25; y <= 1.25; y += 1.25 )
  79. for ( float x = -1.25; x <= 1.25; x += 1.25 ) {
  80. vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );
  81. // doesn't seem to produce any noticeable visual difference compared to simple texture2D lookup
  82. //vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );
  83. float fDepth = unpackDepth( rgbaDepth );
  84. if ( fDepth < shadowCoord.z )
  85. shadow += 1.0;
  86. }
  87. shadow /= 9.0;
  88. */
  89. shadowCoord.z += shadowBias[ i ];
  90. const float ShadowDelta = 1.0 / 9.0;
  91. float xPixelOffset = texelSizeX;
  92. float yPixelOffset = texelSizeY;
  93. float dx0 = - 1.25 * xPixelOffset;
  94. float dy0 = - 1.25 * yPixelOffset;
  95. float dx1 = 1.25 * xPixelOffset;
  96. float dy1 = 1.25 * yPixelOffset;
  97. float fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
  98. if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
  99. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
  100. if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
  101. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
  102. if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
  103. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
  104. if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
  105. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
  106. if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
  107. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
  108. if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
  109. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
  110. if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
  111. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
  112. if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
  113. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
  114. if ( fDepth < shadowCoord.z ) shadow += ShadowDelta;
  115. shadow *= shadowDarkness[ i ];
  116. #elif defined( SHADOWMAP_TYPE_PCF_SOFT )
  117. // Percentage-close filtering
  118. // (9 pixel kernel)
  119. // http://fabiensanglard.net/shadowmappingPCF/
  120. shadowCoord.z += shadowBias[ i ];
  121. float xPixelOffset = texelSizeX;
  122. float yPixelOffset = texelSizeY;
  123. float dx0 = - 1.0 * xPixelOffset;
  124. float dy0 = - 1.0 * yPixelOffset;
  125. float dx1 = 1.0 * xPixelOffset;
  126. float dy1 = 1.0 * yPixelOffset;
  127. mat3 shadowKernel;
  128. mat3 depthKernel;
  129. depthKernel[ 0 ][ 0 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
  130. depthKernel[ 0 ][ 1 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
  131. depthKernel[ 0 ][ 2 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
  132. depthKernel[ 1 ][ 0 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
  133. depthKernel[ 1 ][ 1 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
  134. depthKernel[ 1 ][ 2 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
  135. depthKernel[ 2 ][ 0 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
  136. depthKernel[ 2 ][ 1 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
  137. depthKernel[ 2 ][ 2 ] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
  138. vec3 shadowZ = vec3( shadowCoord.z );
  139. shadowKernel[ 0 ] = vec3( lessThan( depthKernel[ 0 ], shadowZ ) );
  140. shadowKernel[ 0 ] *= vec3( 0.25 );
  141. shadowKernel[ 1 ] = vec3( lessThan( depthKernel[ 1 ], shadowZ ) );
  142. shadowKernel[ 1 ] *= vec3( 0.25 );
  143. shadowKernel[ 2 ] = vec3( lessThan( depthKernel[ 2 ], shadowZ ) );
  144. shadowKernel[ 2 ] *= vec3( 0.25 );
  145. vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[ i ].xy );
  146. shadowKernel[ 0 ] = mix( shadowKernel[ 1 ], shadowKernel[ 0 ], fractionalCoord.x );
  147. shadowKernel[ 1 ] = mix( shadowKernel[ 2 ], shadowKernel[ 1 ], fractionalCoord.x );
  148. vec4 shadowValues;
  149. shadowValues.x = mix( shadowKernel[ 0 ][ 1 ], shadowKernel[ 0 ][ 0 ], fractionalCoord.y );
  150. shadowValues.y = mix( shadowKernel[ 0 ][ 2 ], shadowKernel[ 0 ][ 1 ], fractionalCoord.y );
  151. shadowValues.z = mix( shadowKernel[ 1 ][ 1 ], shadowKernel[ 1 ][ 0 ], fractionalCoord.y );
  152. shadowValues.w = mix( shadowKernel[ 1 ][ 2 ], shadowKernel[ 1 ][ 1 ], fractionalCoord.y );
  153. shadow = dot( shadowValues, vec4( 1.0 ) ) * shadowDarkness[ i ];
  154. #else // no percentage-closer filtering:
  155. shadowCoord.z += shadowBias[ i ];
  156. vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
  157. float fDepth = unpackDepth( rgbaDepth );
  158. if ( fDepth < shadowCoord.z )
  159. shadow = shadowDarkness[ i ];
  160. #endif
  161. }
  162. #ifdef SHADOWMAP_DEBUG
  163. if ( inFrustum ) {
  164. if ( i == 0 ) {
  165. outgoingLight *= vec3( 1.0, 0.5, 0.0 );
  166. } else if ( i == 1 ) {
  167. outgoingLight *= vec3( 0.0, 1.0, 0.8 );
  168. } else {
  169. outgoingLight *= vec3( 0.0, 0.5, 1.0 );
  170. }
  171. }
  172. #endif
  173. #if defined( POINT_LIGHT_SHADOWS )
  174. }
  175. #endif
  176. shadowMask = shadowMask * vec3( 1.0 - shadow );
  177. shadows[ i ] = 1.0 - shadow;
  178. }
  179. #endif