shadowmap_fragment.glsl 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #ifdef USE_SHADOWMAP
  2. #ifdef SHADOWMAP_DEBUG
  3. vec3 frustumColors[3];
  4. frustumColors[0] = vec3( 1.0, 0.5, 0.0 );
  5. frustumColors[1] = vec3( 0.0, 1.0, 0.8 );
  6. frustumColors[2] = vec3( 0.0, 0.5, 1.0 );
  7. #endif
  8. float fDepth;
  9. vec3 shadowColor = vec3( 1.0 );
  10. for( int i = 0; i < MAX_SHADOWS; i ++ ) {
  11. // to save on uniform space, we use the sign of @shadowDarkness[ i ] to determine
  12. // whether or not this light is a point light ( shadowDarkness[ i ] < 0 == point light)
  13. bool isPointLight = shadowDarkness[ i ] < 0.0;
  14. // get the real shadow darkness
  15. float realShadowDarkness = abs( shadowDarkness[ i ] );
  16. // for point lights, the uniform @vShadowCoord is re-purposed to hold
  17. // the distance from the light to the world-space position of the fragment.
  18. vec3 lightToPosition = vShadowCoord[ i ].xyz;
  19. float texelSizeX = 1.0 / shadowMapSize[ i ].x;
  20. float texelSizeY = 1.0 / shadowMapSize[ i ].y;
  21. vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;
  22. float shadow = 0.0;
  23. // if ( something && something ) breaks ATI OpenGL shader compiler
  24. // if ( all( something, something ) ) using this instead
  25. bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );
  26. bool inFrustum = all( inFrustumVec );
  27. bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );
  28. bool frustumTest = all( frustumTestVec );
  29. if ( frustumTest || isPointLight ) {
  30. #if defined( SHADOWMAP_TYPE_PCF )
  31. #if defined(POINT_LIGHT_SHADOWS)
  32. if( isPointLight ) {
  33. // bd3D = base direction 3D
  34. vec3 bd3D = normalize( lightToPosition );
  35. // dp = distance from light to fragment position
  36. float dp = length( lightToPosition );
  37. shadow = 0.0;
  38. // base measurement
  39. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
  40. // dr = disk radius
  41. const float dr = 1.25;
  42. // os = offset scale
  43. float os = dr * 2.0 * texelSizeY;
  44. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd0 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  45. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd1 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  46. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd2 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  47. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd3 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  48. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd4 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  49. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd5 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  50. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd6 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  51. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd7 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  52. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd8 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  53. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd9 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  54. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd10 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  55. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd11 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  56. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd12 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  57. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd13 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  58. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd14 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  59. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd15 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  60. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd16 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  61. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd17 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  62. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd18 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  63. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd19 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  64. shadow /= 21.0;
  65. } else {
  66. #endif
  67. // Percentage-close filtering
  68. // (9 pixel kernel)
  69. // http://fabiensanglard.net/shadowmappingPCF/
  70. /*
  71. // nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
  72. // must enroll loop manually
  73. for ( float y = -1.25; y <= 1.25; y += 1.25 )
  74. for ( float x = -1.25; x <= 1.25; x += 1.25 ) {
  75. vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );
  76. // doesn't seem to produce any noticeable visual difference compared to simple texture2D lookup
  77. //vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );
  78. float fDepth = unpackDepth( rgbaDepth );
  79. if ( fDepth < shadowCoord.z )
  80. shadow += 1.0;
  81. }
  82. shadow /= 9.0;
  83. */
  84. shadowCoord.z += shadowBias[ i ];
  85. const float shadowDelta = 1.0 / 9.0;
  86. float xPixelOffset = texelSizeX;
  87. float yPixelOffset = texelSizeY;
  88. float dx0 = -1.25 * xPixelOffset;
  89. float dy0 = -1.25 * yPixelOffset;
  90. float dx1 = 1.25 * xPixelOffset;
  91. float dy1 = 1.25 * yPixelOffset;
  92. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
  93. if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
  94. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
  95. if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
  96. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
  97. if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
  98. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
  99. if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
  100. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
  101. if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
  102. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
  103. if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
  104. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
  105. if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
  106. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
  107. if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
  108. fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
  109. if ( fDepth < shadowCoord.z ) shadow += shadowDelta;
  110. #if defined(POINT_LIGHT_SHADOWS)
  111. }
  112. #endif
  113. shadowColor = shadowColor * vec3( ( 1.0 - realShadowDarkness * shadow ) );
  114. #elif defined( SHADOWMAP_TYPE_PCF_SOFT )
  115. #if defined(POINT_LIGHT_SHADOWS)
  116. if( isPointLight ) {
  117. // bd3D = base direction 3D
  118. vec3 bd3D = normalize( lightToPosition );
  119. // dp = distance from light to fragment position
  120. float dp = length( lightToPosition );
  121. shadow = 0.0;
  122. // base measurement
  123. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
  124. // dr = disk radius
  125. const float dr = 2.25;
  126. // os = offset scale
  127. float os = dr * 2.0 * texelSizeY;
  128. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd0 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  129. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd1 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  130. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd2 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  131. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd3 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  132. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd4 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  133. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd5 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  134. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd6 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  135. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd7 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  136. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd8 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  137. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd9 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  138. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd10 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  139. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd11 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  140. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd12 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  141. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd13 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  142. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd14 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  143. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd15 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  144. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd16 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  145. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd17 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  146. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd18 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  147. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D + gsd19 * os, texelSizeY ) ), shadowBias[ i ], shadow );
  148. shadow /= 21.0;
  149. } else {
  150. #endif
  151. // Percentage-close filtering
  152. // (9 pixel kernel)
  153. // http://fabiensanglard.net/shadowmappingPCF/
  154. shadowCoord.z += shadowBias[ i ];
  155. float xPixelOffset = texelSizeX;
  156. float yPixelOffset = texelSizeY;
  157. float dx0 = -1.0 * xPixelOffset;
  158. float dy0 = -1.0 * yPixelOffset;
  159. float dx1 = 1.0 * xPixelOffset;
  160. float dy1 = 1.0 * yPixelOffset;
  161. mat3 shadowKernel;
  162. mat3 depthKernel;
  163. depthKernel[0][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );
  164. depthKernel[0][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );
  165. depthKernel[0][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );
  166. depthKernel[1][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );
  167. depthKernel[1][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );
  168. depthKernel[1][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );
  169. depthKernel[2][0] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );
  170. depthKernel[2][1] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );
  171. depthKernel[2][2] = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );
  172. vec3 shadowZ = vec3( shadowCoord.z );
  173. shadowKernel[0] = vec3(lessThan(depthKernel[0], shadowZ ));
  174. shadowKernel[0] *= vec3(0.25);
  175. shadowKernel[1] = vec3(lessThan(depthKernel[1], shadowZ ));
  176. shadowKernel[1] *= vec3(0.25);
  177. shadowKernel[2] = vec3(lessThan(depthKernel[2], shadowZ ));
  178. shadowKernel[2] *= vec3(0.25);
  179. vec2 fractionalCoord = 1.0 - fract( shadowCoord.xy * shadowMapSize[i].xy );
  180. shadowKernel[0] = mix( shadowKernel[1], shadowKernel[0], fractionalCoord.x );
  181. shadowKernel[1] = mix( shadowKernel[2], shadowKernel[1], fractionalCoord.x );
  182. vec4 shadowValues;
  183. shadowValues.x = mix( shadowKernel[0][1], shadowKernel[0][0], fractionalCoord.y );
  184. shadowValues.y = mix( shadowKernel[0][2], shadowKernel[0][1], fractionalCoord.y );
  185. shadowValues.z = mix( shadowKernel[1][1], shadowKernel[1][0], fractionalCoord.y );
  186. shadowValues.w = mix( shadowKernel[1][2], shadowKernel[1][1], fractionalCoord.y );
  187. shadow = dot( shadowValues, vec4( 1.0 ) );
  188. #if defined(POINT_LIGHT_SHADOWS)
  189. }
  190. #endif
  191. shadowColor = shadowColor * vec3( ( 1.0 - realShadowDarkness * shadow ) );
  192. #else
  193. #if defined(POINT_LIGHT_SHADOWS)
  194. if( isPointLight ) {
  195. vec3 bd3D = normalize( lightToPosition );
  196. float dp = length( lightToPosition );
  197. float shadow = 0.0;
  198. adjustShadowValue1K( dp, texture2D( shadowMap[ i ], cubeToUV( bd3D, texelSizeY ) ), shadowBias[ i ], shadow );
  199. shadowColor = shadowColor * vec3( 1.0 - realShadowDarkness * shadow );
  200. } else {
  201. #endif
  202. shadowCoord.z += shadowBias[ i ];
  203. vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );
  204. float fDepth = unpackDepth( rgbaDepth );
  205. if ( fDepth < shadowCoord.z )
  206. // spot with multiple shadows is darker
  207. shadowColor = shadowColor * vec3( 1.0 - realShadowDarkness );
  208. // spot with multiple shadows has the same color as single shadow spot
  209. // shadowColor = min( shadowColor, vec3( realShadowDarkness ) );
  210. #if defined(POINT_LIGHT_SHADOWS)
  211. }
  212. #endif
  213. #endif
  214. }
  215. #ifdef SHADOWMAP_DEBUG
  216. if ( inFrustum ) outgoingLight *= frustumColors[ i ];
  217. #endif
  218. }
  219. outgoingLight = outgoingLight * shadowColor;
  220. #endif