shadowsFragmentFunctions.fx 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #ifdef SHADOWS
  2. #ifndef SHADOWFLOAT
  3. float unpack(vec4 color)
  4. {
  5. const vec4 bit_shift = vec4(1.0 / (255.0 * 255.0 * 255.0), 1.0 / (255.0 * 255.0), 1.0 / 255.0, 1.0);
  6. return dot(color, bit_shift);
  7. }
  8. #endif
  9. float computeShadowCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, vec2 depthValues)
  10. {
  11. vec3 directionToLight = vPositionW - lightPosition;
  12. float depth = length(directionToLight);
  13. depth = (depth + depthValues.x) / (depthValues.y);
  14. depth = clamp(depth, 0., 1.0);
  15. directionToLight = normalize(directionToLight);
  16. directionToLight.y = -directionToLight.y;
  17. #ifndef SHADOWFLOAT
  18. float shadow = unpack(textureCube(shadowSampler, directionToLight));
  19. #else
  20. float shadow = textureCube(shadowSampler, directionToLight).x;
  21. #endif
  22. if (depth > shadow)
  23. {
  24. return darkness;
  25. }
  26. return 1.0;
  27. }
  28. float computeShadowWithPoissonSamplingCube(vec3 lightPosition, samplerCube shadowSampler, float mapSize, float darkness, vec2 depthValues)
  29. {
  30. vec3 directionToLight = vPositionW - lightPosition;
  31. float depth = length(directionToLight);
  32. depth = (depth + depthValues.x) / (depthValues.y);
  33. depth = clamp(depth, 0., 1.0);
  34. directionToLight = normalize(directionToLight);
  35. directionToLight.y = -directionToLight.y;
  36. float visibility = 1.;
  37. vec3 poissonDisk[4];
  38. poissonDisk[0] = vec3(-1.0, 1.0, -1.0);
  39. poissonDisk[1] = vec3(1.0, -1.0, -1.0);
  40. poissonDisk[2] = vec3(-1.0, -1.0, -1.0);
  41. poissonDisk[3] = vec3(1.0, -1.0, 1.0);
  42. // Poisson Sampling
  43. #ifndef SHADOWFLOAT
  44. if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[0] * mapSize)) < depth) visibility -= 0.25;
  45. if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[1] * mapSize)) < depth) visibility -= 0.25;
  46. if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[2] * mapSize)) < depth) visibility -= 0.25;
  47. if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[3] * mapSize)) < depth) visibility -= 0.25;
  48. #else
  49. if (textureCube(shadowSampler, directionToLight + poissonDisk[0] * mapSize).x < depth) visibility -= 0.25;
  50. if (textureCube(shadowSampler, directionToLight + poissonDisk[1] * mapSize).x < depth) visibility -= 0.25;
  51. if (textureCube(shadowSampler, directionToLight + poissonDisk[2] * mapSize).x < depth) visibility -= 0.25;
  52. if (textureCube(shadowSampler, directionToLight + poissonDisk[3] * mapSize).x < depth) visibility -= 0.25;
  53. #endif
  54. return min(1.0, visibility + darkness);
  55. }
  56. #ifdef WEBGL2
  57. float computeShadowWithPCFCube(vec3 lightPosition, samplerCubeShadow shadowSampler, float darkness, vec2 depthValues)
  58. {
  59. vec4 directionToLight = vec4(vPositionW - lightPosition, 1.0);
  60. directionToLight.w = length(directionToLight.xyz);
  61. directionToLight.w = (directionToLight.w + depthValues.x) / (depthValues.y);
  62. directionToLight.w = clamp(directionToLight.w, 0., 1.0);
  63. directionToLight.xyz = normalize(directionToLight.xyz);
  64. directionToLight.y = -directionToLight.y;
  65. float shadow = textureCube(shadowSampler, directionToLight);
  66. if (shadow < 1.0)
  67. {
  68. return shadow * (1. - darkness) + darkness;
  69. }
  70. return 1.0;
  71. }
  72. #endif
  73. float computeShadowWithESMCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, float depthScale, vec2 depthValues)
  74. {
  75. vec3 directionToLight = vPositionW - lightPosition;
  76. float depth = length(directionToLight);
  77. depth = (depth + depthValues.x) / (depthValues.y);
  78. float shadowPixelDepth = clamp(depth, 0., 1.0);
  79. directionToLight = normalize(directionToLight);
  80. directionToLight.y = -directionToLight.y;
  81. #ifndef SHADOWFLOAT
  82. float shadowMapSample = unpack(textureCube(shadowSampler, directionToLight));
  83. #else
  84. float shadowMapSample = textureCube(shadowSampler, directionToLight).x;
  85. #endif
  86. float esm = 1.0 - clamp(exp(min(87., depthScale * shadowPixelDepth)) * shadowMapSample, 0., 1. - darkness);
  87. return esm;
  88. }
  89. float computeShadowWithCloseESMCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, float depthScale, vec2 depthValues)
  90. {
  91. vec3 directionToLight = vPositionW - lightPosition;
  92. float depth = length(directionToLight);
  93. depth = (depth + depthValues.x) / (depthValues.y);
  94. float shadowPixelDepth = clamp(depth, 0., 1.0);
  95. directionToLight = normalize(directionToLight);
  96. directionToLight.y = -directionToLight.y;
  97. #ifndef SHADOWFLOAT
  98. float shadowMapSample = unpack(textureCube(shadowSampler, directionToLight));
  99. #else
  100. float shadowMapSample = textureCube(shadowSampler, directionToLight).x;
  101. #endif
  102. float esm = clamp(exp(min(87., -depthScale * (shadowPixelDepth - shadowMapSample))), darkness, 1.);
  103. return esm;
  104. }
  105. float computeShadow(vec4 vPositionFromLight, float depthMetric, sampler2D shadowSampler, float darkness, float frustumEdgeFalloff)
  106. {
  107. vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
  108. vec2 uv = 0.5 * clipSpace.xy + vec2(0.5);
  109. if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
  110. {
  111. return 1.0;
  112. }
  113. float shadowPixelDepth = clamp(depthMetric, 0., 1.0);
  114. #ifndef SHADOWFLOAT
  115. float shadow = unpack(texture2D(shadowSampler, uv));
  116. #else
  117. float shadow = texture2D(shadowSampler, uv).x;
  118. #endif
  119. if (shadowPixelDepth > shadow)
  120. {
  121. return computeFallOff(darkness, clipSpace.xy, frustumEdgeFalloff);
  122. }
  123. return 1.;
  124. }
  125. float computeShadowWithPoissonSampling(vec4 vPositionFromLight, float depthMetric, sampler2D shadowSampler, float mapSize, float darkness, float frustumEdgeFalloff)
  126. {
  127. vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
  128. vec2 uv = 0.5 * clipSpace.xy + vec2(0.5);
  129. if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
  130. {
  131. return 1.0;
  132. }
  133. float shadowPixelDepth = clamp(depthMetric, 0., 1.0);
  134. float visibility = 1.;
  135. vec2 poissonDisk[4];
  136. poissonDisk[0] = vec2(-0.94201624, -0.39906216);
  137. poissonDisk[1] = vec2(0.94558609, -0.76890725);
  138. poissonDisk[2] = vec2(-0.094184101, -0.92938870);
  139. poissonDisk[3] = vec2(0.34495938, 0.29387760);
  140. // Poisson Sampling
  141. #ifndef SHADOWFLOAT
  142. if (unpack(texture2D(shadowSampler, uv + poissonDisk[0] * mapSize)) < shadowPixelDepth) visibility -= 0.25;
  143. if (unpack(texture2D(shadowSampler, uv + poissonDisk[1] * mapSize)) < shadowPixelDepth) visibility -= 0.25;
  144. if (unpack(texture2D(shadowSampler, uv + poissonDisk[2] * mapSize)) < shadowPixelDepth) visibility -= 0.25;
  145. if (unpack(texture2D(shadowSampler, uv + poissonDisk[3] * mapSize)) < shadowPixelDepth) visibility -= 0.25;
  146. #else
  147. if (texture2D(shadowSampler, uv + poissonDisk[0] * mapSize).x < shadowPixelDepth) visibility -= 0.25;
  148. if (texture2D(shadowSampler, uv + poissonDisk[1] * mapSize).x < shadowPixelDepth) visibility -= 0.25;
  149. if (texture2D(shadowSampler, uv + poissonDisk[2] * mapSize).x < shadowPixelDepth) visibility -= 0.25;
  150. if (texture2D(shadowSampler, uv + poissonDisk[3] * mapSize).x < shadowPixelDepth) visibility -= 0.25;
  151. #endif
  152. return computeFallOff(min(1.0, visibility + darkness), clipSpace.xy, frustumEdgeFalloff);
  153. }
  154. #ifdef WEBGL2
  155. float computeShadowWithPCF(vec4 vPositionFromLight, float depthMetric, sampler2DShadow shadowSampler, float darkness, float frustumEdgeFalloff)
  156. {
  157. vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
  158. //vec3 uvDepth = vec3(0.5 * clipSpace.xyz + vec3(0.5));
  159. vec3 uvDepth = vec3(0.5 * clipSpace.xy + vec2(0.5), depthMetric);
  160. if (uvDepth.x < 0. || uvDepth.x > 1.0 || uvDepth.y < 0. || uvDepth.y > 1.0)
  161. {
  162. return 1.0;
  163. }
  164. float shadow = texture2D(shadowSampler, uvDepth);
  165. if (shadow < 1.0)
  166. {
  167. shadow = shadow * (1. - darkness) + darkness;
  168. return computeFallOff(shadow, clipSpace.xy, frustumEdgeFalloff);
  169. }
  170. return 1.0;
  171. }
  172. #endif
  173. float computeShadowWithESM(vec4 vPositionFromLight, float depthMetric, sampler2D shadowSampler, float darkness, float depthScale, float frustumEdgeFalloff)
  174. {
  175. vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
  176. vec2 uv = 0.5 * clipSpace.xy + vec2(0.5);
  177. if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
  178. {
  179. return 1.0;
  180. }
  181. float shadowPixelDepth = clamp(depthMetric, 0., 1.0);
  182. #ifndef SHADOWFLOAT
  183. float shadowMapSample = unpack(texture2D(shadowSampler, uv));
  184. #else
  185. float shadowMapSample = texture2D(shadowSampler, uv).x;
  186. #endif
  187. float esm = 1.0 - clamp(exp(min(87., depthScale * shadowPixelDepth)) * shadowMapSample, 0., 1. - darkness);
  188. return computeFallOff(esm, clipSpace.xy, frustumEdgeFalloff);
  189. }
  190. float computeShadowWithCloseESM(vec4 vPositionFromLight, float depthMetric, sampler2D shadowSampler, float darkness, float depthScale, float frustumEdgeFalloff)
  191. {
  192. vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
  193. vec2 uv = 0.5 * clipSpace.xy + vec2(0.5);
  194. if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
  195. {
  196. return 1.0;
  197. }
  198. float shadowPixelDepth = clamp(depthMetric, 0., 1.0);
  199. #ifndef SHADOWFLOAT
  200. float shadowMapSample = unpack(texture2D(shadowSampler, uv));
  201. #else
  202. float shadowMapSample = texture2D(shadowSampler, uv).x;
  203. #endif
  204. float esm = clamp(exp(min(87., -depthScale * (shadowPixelDepth - shadowMapSample))), darkness, 1.);
  205. return computeFallOff(esm, clipSpace.xy, frustumEdgeFalloff);
  206. }
  207. #endif