pbrShadowFunctions.fx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // Shadows
  2. #ifdef SHADOWS
  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. #if defined(POINTLIGHT0) || defined(POINTLIGHT1) || defined(POINTLIGHT2) || defined(POINTLIGHT3)
  9. uniform vec2 depthValues;
  10. float computeShadowCube(vec3 lightPosition, samplerCube shadowSampler, float darkness, float bias)
  11. {
  12. vec3 directionToLight = vPositionW - lightPosition;
  13. float depth = length(directionToLight);
  14. depth = clamp(depth, 0., 1.0);
  15. directionToLight = normalize(directionToLight);
  16. directionToLight.y = - directionToLight.y;
  17. float shadow = unpack(textureCube(shadowSampler, directionToLight)) + bias;
  18. if (depth > shadow)
  19. {
  20. #ifdef OVERLOADEDSHADOWVALUES
  21. return mix(1.0, darkness, vOverloadedShadowIntensity.x);
  22. #else
  23. return darkness;
  24. #endif
  25. }
  26. return 1.0;
  27. }
  28. float computeShadowWithPCFCube(vec3 lightPosition, samplerCube shadowSampler, float mapSize, float bias, float darkness)
  29. {
  30. vec3 directionToLight = vPositionW - lightPosition;
  31. float depth = length(directionToLight);
  32. depth = (depth - depthValues.x) / (depthValues.y - depthValues.x);
  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. float biasedDepth = depth - bias;
  44. if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[0] * mapSize)) < biasedDepth) visibility -= 0.25;
  45. if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[1] * mapSize)) < biasedDepth) visibility -= 0.25;
  46. if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[2] * mapSize)) < biasedDepth) visibility -= 0.25;
  47. if (unpack(textureCube(shadowSampler, directionToLight + poissonDisk[3] * mapSize)) < biasedDepth) visibility -= 0.25;
  48. #ifdef OVERLOADEDSHADOWVALUES
  49. return min(1.0, mix(1.0, visibility + darkness, vOverloadedShadowIntensity.x));
  50. #else
  51. return min(1.0, visibility + darkness);
  52. #endif
  53. }
  54. #endif
  55. #if defined(SPOTLIGHT0) || defined(SPOTLIGHT1) || defined(SPOTLIGHT2) || defined(SPOTLIGHT3) || defined(DIRLIGHT0) || defined(DIRLIGHT1) || defined(DIRLIGHT2) || defined(DIRLIGHT3)
  56. float computeShadow(vec4 vPositionFromLight, sampler2D shadowSampler, float darkness, float bias)
  57. {
  58. vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
  59. depth = 0.5 * depth + vec3(0.5);
  60. vec2 uv = depth.xy;
  61. if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
  62. {
  63. return 1.0;
  64. }
  65. float shadow = unpack(texture2D(shadowSampler, uv)) + bias;
  66. if (depth.z > shadow)
  67. {
  68. #ifdef OVERLOADEDSHADOWVALUES
  69. return mix(1.0, darkness, vOverloadedShadowIntensity.x);
  70. #else
  71. return darkness;
  72. #endif
  73. }
  74. return 1.;
  75. }
  76. float computeShadowWithPCF(vec4 vPositionFromLight, sampler2D shadowSampler, float mapSize, float bias, float darkness)
  77. {
  78. vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
  79. depth = 0.5 * depth + vec3(0.5);
  80. vec2 uv = depth.xy;
  81. if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0)
  82. {
  83. return 1.0;
  84. }
  85. float visibility = 1.;
  86. vec2 poissonDisk[4];
  87. poissonDisk[0] = vec2(-0.94201624, -0.39906216);
  88. poissonDisk[1] = vec2(0.94558609, -0.76890725);
  89. poissonDisk[2] = vec2(-0.094184101, -0.92938870);
  90. poissonDisk[3] = vec2(0.34495938, 0.29387760);
  91. // Poisson Sampling
  92. float biasedDepth = depth.z - bias;
  93. if (unpack(texture2D(shadowSampler, uv + poissonDisk[0] * mapSize)) < biasedDepth) visibility -= 0.25;
  94. if (unpack(texture2D(shadowSampler, uv + poissonDisk[1] * mapSize)) < biasedDepth) visibility -= 0.25;
  95. if (unpack(texture2D(shadowSampler, uv + poissonDisk[2] * mapSize)) < biasedDepth) visibility -= 0.25;
  96. if (unpack(texture2D(shadowSampler, uv + poissonDisk[3] * mapSize)) < biasedDepth) visibility -= 0.25;
  97. #ifdef OVERLOADEDSHADOWVALUES
  98. return min(1.0, mix(1.0, visibility + darkness, vOverloadedShadowIntensity.x));
  99. #else
  100. return min(1.0, visibility + darkness);
  101. #endif
  102. }
  103. // Thanks to http://devmaster.net/
  104. float unpackHalf(vec2 color)
  105. {
  106. return color.x + (color.y / 255.0);
  107. }
  108. float linstep(float low, float high, float v) {
  109. return clamp((v - low) / (high - low), 0.0, 1.0);
  110. }
  111. float ChebychevInequality(vec2 moments, float compare, float bias)
  112. {
  113. float p = smoothstep(compare - bias, compare, moments.x);
  114. float variance = max(moments.y - moments.x * moments.x, 0.02);
  115. float d = compare - moments.x;
  116. float p_max = linstep(0.2, 1.0, variance / (variance + d * d));
  117. return clamp(max(p, p_max), 0.0, 1.0);
  118. }
  119. float computeShadowWithVSM(vec4 vPositionFromLight, sampler2D shadowSampler, float bias, float darkness)
  120. {
  121. vec3 depth = vPositionFromLight.xyz / vPositionFromLight.w;
  122. depth = 0.5 * depth + vec3(0.5);
  123. vec2 uv = depth.xy;
  124. if (uv.x < 0. || uv.x > 1.0 || uv.y < 0. || uv.y > 1.0 || depth.z >= 1.0)
  125. {
  126. return 1.0;
  127. }
  128. vec4 texel = texture2D(shadowSampler, uv);
  129. vec2 moments = vec2(unpackHalf(texel.xy), unpackHalf(texel.zw));
  130. #ifdef OVERLOADEDSHADOWVALUES
  131. return min(1.0, mix(1.0, 1.0 - ChebychevInequality(moments, depth.z, bias) + darkness, vOverloadedShadowIntensity.x));
  132. #else
  133. return min(1.0, 1.0 - ChebychevInequality(moments, depth.z, bias) + darkness);
  134. #endif
  135. }
  136. #endif
  137. #endif