shadowsFragmentFunctions.fx 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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 computeShadowWithPCFCube(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. float computeShadowWithESMCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, float depthScale, vec2 depthValues)
  57. {
  58. vec3 directionToLight = vPositionW - lightPosition;
  59. float depth = length(directionToLight);
  60. depth = (depth + depthValues.x) / (depthValues.y);
  61. float shadowPixelDepth = clamp(depth, 0., 1.0);
  62. directionToLight = normalize(directionToLight);
  63. directionToLight.y = -directionToLight.y;
  64. #ifndef SHADOWFLOAT
  65. float shadowMapSample = unpack(textureCube(shadowSampler, directionToLight));
  66. #else
  67. float shadowMapSample = textureCube(shadowSampler, directionToLight).x;
  68. #endif
  69. float esm = 1.0 - clamp(exp(min(87., depthScale * shadowPixelDepth)) * shadowMapSample, 0., 1. - darkness);
  70. return esm;
  71. }
  72. float computeShadowWithCloseESMCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, float depthScale, vec2 depthValues)
  73. {
  74. vec3 directionToLight = vPositionW - lightPosition;
  75. float depth = length(directionToLight);
  76. depth = (depth + depthValues.x) / (depthValues.y);
  77. float shadowPixelDepth = clamp(depth, 0., 1.0);
  78. directionToLight = normalize(directionToLight);
  79. directionToLight.y = -directionToLight.y;
  80. #ifndef SHADOWFLOAT
  81. float shadowMapSample = unpack(textureCube(shadowSampler, directionToLight));
  82. #else
  83. float shadowMapSample = textureCube(shadowSampler, directionToLight).x;
  84. #endif
  85. float esm = clamp(exp(min(87., -depthScale * (shadowPixelDepth - shadowMapSample))), darkness, 1.);
  86. return esm;
  87. }
  88. float computeShadow(vec4 vPositionFromLight, float depthMetric, sampler2D shadowSampler, float darkness, float frustumEdgeFalloff)
  89. {
  90. vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
  91. vec2 uv = 0.5 * clipSpace.xy + vec2(0.5);
  92. if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
  93. {
  94. return 1.0;
  95. }
  96. float shadowPixelDepth = clamp(depthMetric, 0., 1.0);
  97. #ifndef SHADOWFLOAT
  98. float shadow = unpack(texture2D(shadowSampler, uv));
  99. #else
  100. float shadow = texture2D(shadowSampler, uv).x;
  101. #endif
  102. if (shadowPixelDepth > shadow)
  103. {
  104. return computeFallOff(darkness, clipSpace.xy, frustumEdgeFalloff);
  105. }
  106. return 1.;
  107. }
  108. float computeShadowWithPCF(vec4 vPositionFromLight, float depthMetric, sampler2D shadowSampler, float mapSize, float darkness, float frustumEdgeFalloff)
  109. {
  110. vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
  111. vec2 uv = 0.5 * clipSpace.xy + vec2(0.5);
  112. if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
  113. {
  114. return 1.0;
  115. }
  116. float shadowPixelDepth = clamp(depthMetric, 0., 1.0);
  117. float visibility = 1.;
  118. vec2 poissonDisk[4];
  119. poissonDisk[0] = vec2(-0.94201624, -0.39906216);
  120. poissonDisk[1] = vec2(0.94558609, -0.76890725);
  121. poissonDisk[2] = vec2(-0.094184101, -0.92938870);
  122. poissonDisk[3] = vec2(0.34495938, 0.29387760);
  123. // Poisson Sampling
  124. #ifndef SHADOWFLOAT
  125. if (unpack(texture2D(shadowSampler, uv + poissonDisk[0] * mapSize)) < shadowPixelDepth) visibility -= 0.25;
  126. if (unpack(texture2D(shadowSampler, uv + poissonDisk[1] * mapSize)) < shadowPixelDepth) visibility -= 0.25;
  127. if (unpack(texture2D(shadowSampler, uv + poissonDisk[2] * mapSize)) < shadowPixelDepth) visibility -= 0.25;
  128. if (unpack(texture2D(shadowSampler, uv + poissonDisk[3] * mapSize)) < shadowPixelDepth) visibility -= 0.25;
  129. #else
  130. if (texture2D(shadowSampler, uv + poissonDisk[0] * mapSize).x < shadowPixelDepth) visibility -= 0.25;
  131. if (texture2D(shadowSampler, uv + poissonDisk[1] * mapSize).x < shadowPixelDepth) visibility -= 0.25;
  132. if (texture2D(shadowSampler, uv + poissonDisk[2] * mapSize).x < shadowPixelDepth) visibility -= 0.25;
  133. if (texture2D(shadowSampler, uv + poissonDisk[3] * mapSize).x < shadowPixelDepth) visibility -= 0.25;
  134. #endif
  135. return computeFallOff(min(1.0, visibility + darkness), clipSpace.xy, frustumEdgeFalloff);
  136. }
  137. float computeShadowWithESM(vec4 vPositionFromLight, float depthMetric, sampler2D shadowSampler, float darkness, float depthScale, float frustumEdgeFalloff)
  138. {
  139. vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
  140. vec2 uv = 0.5 * clipSpace.xy + vec2(0.5);
  141. if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
  142. {
  143. return 1.0;
  144. }
  145. float shadowPixelDepth = clamp(depthMetric, 0., 1.0);
  146. #ifndef SHADOWFLOAT
  147. float shadowMapSample = unpack(texture2D(shadowSampler, uv));
  148. #else
  149. float shadowMapSample = texture2D(shadowSampler, uv).x;
  150. #endif
  151. float esm = 1.0 - clamp(exp(min(87., depthScale * shadowPixelDepth)) * shadowMapSample, 0., 1. - darkness);
  152. return computeFallOff(esm, clipSpace.xy, frustumEdgeFalloff);
  153. }
  154. float computeShadowWithCloseESM(vec4 vPositionFromLight, float depthMetric, sampler2D shadowSampler, float darkness, float depthScale, float frustumEdgeFalloff)
  155. {
  156. vec3 clipSpace = vPositionFromLight.xyz / vPositionFromLight.w;
  157. vec2 uv = 0.5 * clipSpace.xy + vec2(0.5);
  158. if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
  159. {
  160. return 1.0;
  161. }
  162. float shadowPixelDepth = clamp(depthMetric, 0., 1.0);
  163. #ifndef SHADOWFLOAT
  164. float shadowMapSample = unpack(texture2D(shadowSampler, uv));
  165. #else
  166. float shadowMapSample = texture2D(shadowSampler, uv).x;
  167. #endif
  168. float esm = clamp(exp(min(87., -depthScale * (shadowPixelDepth - shadowMapSample))), darkness, 1.);
  169. return computeFallOff(esm, clipSpace.xy, frustumEdgeFalloff);
  170. }
  171. #endif