2
0

shadow.glsl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /* light.glsl -- Contains shadow map sampling functions
  2. *
  3. * Copyright (c) 2025-2026 Le Juez Victor
  4. *
  5. * This software is provided 'as-is', without any express or implied warranty.
  6. * For conditions of distribution and use, see accompanying LICENSE file.
  7. */
  8. /* === Includes === */
  9. #include "light.glsl"
  10. #include "../math.glsl"
  11. /* === Constants === */
  12. #define SHADOW_SAMPLES 8
  13. const vec2 VOGEL_DISK[8] = vec2[8](
  14. vec2(0.250000, 0.000000),
  15. vec2(-0.319290, 0.292496),
  16. vec2(0.048872, -0.556877),
  17. vec2(0.402444, 0.524918),
  18. vec2(-0.738535, -0.130636),
  19. vec2(0.699605, -0.445031),
  20. vec2(-0.234004, 0.870484),
  21. vec2(-0.446271, -0.859268)
  22. );
  23. /* === Functions === */
  24. mat2 S_DebandingRotationMatrix()
  25. {
  26. float r = M_TAU * M_HashIGN(gl_FragCoord.xy);
  27. float sr = sin(r), cr = cos(r);
  28. return mat2(vec2(cr, -sr), vec2(sr, cr));
  29. }
  30. #ifdef NUM_FORWARD_LIGHTS
  31. float S_SampleShadowDir(int lightIndex, vec4 projPos, float cNdotL)
  32. {
  33. #define light uLights[lightIndex]
  34. #else
  35. float S_SampleShadowDir(vec4 projPos, float cNdotL)
  36. {
  37. #define light uLight
  38. #endif
  39. vec3 projCoords = projPos.xyz / projPos.w * 0.5 + 0.5;
  40. float bias = light.shadowSlopeBias * (1.0 - cNdotL);
  41. bias = max(bias, light.shadowDepthBias * projCoords.z);
  42. float compareDepth = projCoords.z - bias;
  43. mat2 diskRot = S_DebandingRotationMatrix();
  44. float shadow = 0.0;
  45. for (int i = 0; i < SHADOW_SAMPLES; ++i) {
  46. vec2 offset = diskRot * VOGEL_DISK[i] * light.shadowSoftness;
  47. shadow += texture(uShadowDirTex, vec4(projCoords.xy + offset, light.shadowLayer, compareDepth));
  48. }
  49. shadow /= float(SHADOW_SAMPLES);
  50. vec3 distToBorder = min(projCoords, 1.0 - projCoords);
  51. float edgeFade = smoothstep(0.0, 0.15, min(distToBorder.x, min(distToBorder.y, distToBorder.z)));
  52. shadow = mix(1.0, shadow, edgeFade);
  53. #undef light
  54. return shadow;
  55. }
  56. #ifdef NUM_FORWARD_LIGHTS
  57. float S_SampleShadowSpot(int lightIndex, vec4 projPos, float cNdotL)
  58. {
  59. #define light uLights[lightIndex]
  60. #else
  61. float S_SampleShadowSpot(vec4 projPos, float cNdotL)
  62. {
  63. #define light uLight
  64. #endif
  65. vec3 projCoords = projPos.xyz / projPos.w * 0.5 + 0.5;
  66. float bias = light.shadowSlopeBias * (1.0 - cNdotL);
  67. bias = max(bias, light.shadowDepthBias * projCoords.z);
  68. float compareDepth = projCoords.z - bias;
  69. mat2 diskRot = S_DebandingRotationMatrix();
  70. float shadow = 0.0;
  71. for (int i = 0; i < SHADOW_SAMPLES; ++i) {
  72. vec2 offset = diskRot * VOGEL_DISK[i] * light.shadowSoftness;
  73. shadow += texture(uShadowSpotTex, vec4(projCoords.xy + offset, light.shadowLayer, compareDepth));
  74. }
  75. #undef light
  76. return shadow / float(SHADOW_SAMPLES);
  77. }
  78. #ifdef NUM_FORWARD_LIGHTS
  79. float S_SampleShadowOmni(int lightIndex, vec3 fragPos, float cNdotL)
  80. {
  81. #define light uLights[lightIndex]
  82. #else
  83. float S_SampleShadowOmni(vec3 fragPos, float cNdotL)
  84. {
  85. #define light uLight
  86. #endif
  87. vec3 lightToFrag = fragPos - light.position;
  88. float currentDepth = length(lightToFrag);
  89. float bias = light.shadowSlopeBias * (1.0 - cNdotL * 0.5);
  90. bias = max(bias, light.shadowDepthBias * currentDepth);
  91. float compareDepth = (currentDepth - bias) / light.far;
  92. mat2 diskRot = S_DebandingRotationMatrix();
  93. mat3 OBN = M_OrthonormalBasis(lightToFrag / currentDepth);
  94. float shadow = 0.0;
  95. for (int i = 0; i < SHADOW_SAMPLES; ++i) {
  96. vec2 diskOffset = diskRot * VOGEL_DISK[i] * light.shadowSoftness;
  97. shadow += texture(uShadowOmniTex, vec4(OBN * vec3(diskOffset.xy, 1.0), light.shadowLayer), compareDepth);
  98. }
  99. #undef light
  100. return shadow / float(SHADOW_SAMPLES);
  101. }