shadows.glsl 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #ifndef _SHADOWS_GLSL_
  2. #define _SHADOWS_GLSL_
  3. #include "compiled.inc"
  4. #ifdef _CSM
  5. uniform vec4 casData[shadowmapCascades * 4 + 4];
  6. #endif
  7. #ifdef _SMSizeUniform
  8. uniform vec2 smSizeUniform;
  9. #endif
  10. float PCF(sampler2DShadow shadowMap, const vec2 uv, const float compare, const vec2 smSize) {
  11. float result = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare));
  12. result += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare));
  13. result += texture(shadowMap, vec3(uv + (vec2(-1.0, 1.0) / smSize), compare));
  14. result += texture(shadowMap, vec3(uv + (vec2(0.0, -1.0) / smSize), compare));
  15. result += texture(shadowMap, vec3(uv, compare));
  16. result += texture(shadowMap, vec3(uv + (vec2(0.0, 1.0) / smSize), compare));
  17. result += texture(shadowMap, vec3(uv + (vec2(1.0, -1.0) / smSize), compare));
  18. result += texture(shadowMap, vec3(uv + (vec2(1.0, 0.0) / smSize), compare));
  19. result += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare));
  20. return result / 9.0;
  21. }
  22. float lpToDepth(vec3 lp, const vec2 lightProj) {
  23. lp = abs(lp);
  24. float zcomp = max(lp.x, max(lp.y, lp.z));
  25. zcomp = lightProj.x - lightProj.y / zcomp;
  26. return zcomp * 0.5 + 0.5;
  27. }
  28. float PCFCube(samplerCubeShadow shadowMapCube, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n) {
  29. const float s = shadowmapCubePcfSize; // TODO: incorrect...
  30. float compare = lpToDepth(lp, lightProj) - bias * 1.5;
  31. ml = ml + n * bias * 20;
  32. #ifdef HLSL
  33. ml.y = -ml.y;
  34. #endif
  35. float result = texture(shadowMapCube, vec4(ml, compare));
  36. result += texture(shadowMapCube, vec4(ml + vec3(s, s, s), compare));
  37. result += texture(shadowMapCube, vec4(ml + vec3(-s, s, s), compare));
  38. result += texture(shadowMapCube, vec4(ml + vec3(s, -s, s), compare));
  39. result += texture(shadowMapCube, vec4(ml + vec3(s, s, -s), compare));
  40. result += texture(shadowMapCube, vec4(ml + vec3(-s, -s, s), compare));
  41. result += texture(shadowMapCube, vec4(ml + vec3(s, -s, -s), compare));
  42. result += texture(shadowMapCube, vec4(ml + vec3(-s, s, -s), compare));
  43. result += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare));
  44. return result / 9.0;
  45. }
  46. float shadowTest(sampler2DShadow shadowMap, const vec3 lPos, const float shadowsBias) {
  47. #ifdef _SMSizeUniform
  48. vec2 smSize = smSizeUniform;
  49. #else
  50. const vec2 smSize = shadowmapSize;
  51. #endif
  52. if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return 1.0;
  53. return PCF(shadowMap, lPos.xy, lPos.z - shadowsBias, smSize);
  54. }
  55. #ifdef _CSM
  56. mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
  57. const int c = shadowmapCascades;
  58. // Get cascade index
  59. // TODO: use bounding box slice selection instead of sphere
  60. const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3));
  61. // int ci;
  62. // if (d < casData[c * 4].x) ci = 0;
  63. // else if (d < casData[c * 4].y) ci = 1 * 4;
  64. // else if (d < casData[c * 4].z) ci = 2 * 4;
  65. // else ci = 3 * 4;
  66. // Splits
  67. vec4 comp = vec4(
  68. float(d > casData[c * 4].x),
  69. float(d > casData[c * 4].y),
  70. float(d > casData[c * 4].z),
  71. float(d > casData[c * 4].w));
  72. casi = int(min(dot(ci, comp), c));
  73. // Get cascade mat
  74. casIndex = casi * 4;
  75. return mat4(
  76. casData[casIndex ],
  77. casData[casIndex + 1],
  78. casData[casIndex + 2],
  79. casData[casIndex + 3]);
  80. // if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]);
  81. // ..
  82. }
  83. float shadowTestCascade(sampler2DShadow shadowMap, const vec3 eye, const vec3 p, const float shadowsBias) {
  84. #ifdef _SMSizeUniform
  85. vec2 smSize = smSizeUniform * vec2(shadowmapCascades, 1.0);
  86. #else
  87. const vec2 smSize = shadowmapSize * vec2(shadowmapCascades, 1.0);
  88. #endif
  89. const int c = shadowmapCascades;
  90. float d = distance(eye, p);
  91. int casi;
  92. int casIndex;
  93. mat4 LWVP = getCascadeMat(d, casi, casIndex);
  94. vec4 lPos = LWVP * vec4(p, 1.0);
  95. lPos.xyz /= lPos.w;
  96. float visibility = 1.0;
  97. if (lPos.w > 0.0) visibility = PCF(shadowMap, lPos.xy, lPos.z - shadowsBias, smSize);
  98. // Blend cascade
  99. // https://github.com/TheRealMJP/Shadows
  100. const float blendThres = 0.15;
  101. float nextSplit = casData[c * 4][casi];
  102. float splitSize = casi == 0 ? nextSplit : nextSplit - casData[c * 4][casi - 1];
  103. float splitDist = (nextSplit - d) / splitSize;
  104. if (splitDist <= blendThres && casi != c - 1) {
  105. int casIndex2 = casIndex + 4;
  106. mat4 LWVP2 = mat4(
  107. casData[casIndex2 ],
  108. casData[casIndex2 + 1],
  109. casData[casIndex2 + 2],
  110. casData[casIndex2 + 3]);
  111. vec4 lPos2 = LWVP2 * vec4(p, 1.0);
  112. lPos2.xyz /= lPos2.w;
  113. float visibility2 = 1.0;
  114. if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, lPos2.xy, lPos2.z - shadowsBias, smSize);
  115. float lerpAmt = smoothstep(0.0, blendThres, splitDist);
  116. return mix(visibility2, visibility, lerpAmt);
  117. }
  118. return visibility;
  119. // Visualize cascades
  120. // if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0);
  121. // if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0);
  122. // if (ci == 8) albedo.rgb = vec3(0.0, 0.0, 1.0);
  123. // if (ci == 12) albedo.rgb = vec3(1.0, 1.0, 0.0);
  124. }
  125. #endif
  126. #endif