RtShadowsSvgfAtrous.ankiprog 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma anki mutator LAST_PASS 0 1
  6. ANKI_SPECIALIZATION_CONSTANT_UVEC2(FB_SIZE, 0u);
  7. #pragma anki start comp
  8. #include <AnKi/Shaders/RtShadows.glsl>
  9. #include <AnKi/Shaders/BilateralFilter.glsl>
  10. #include <AnKi/Shaders/Functions.glsl>
  11. const UVec2 WORKGROUP_SIZE = UVec2(8, 8);
  12. layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
  13. layout(set = 0, binding = 0) uniform sampler u_nearestAnyClampSampler;
  14. layout(set = 0, binding = 1) uniform sampler u_linearAnyClampSampler;
  15. layout(set = 0, binding = 2) uniform texture2D u_depthTex;
  16. layout(set = 0, binding = 3) uniform utexture2D u_shadowsTex;
  17. layout(set = 0, binding = 4) uniform texture2D u_varianceTex;
  18. layout(set = 0, binding = 5) uniform uimage2D u_shadowsImage;
  19. #if !LAST_PASS
  20. layout(set = 0, binding = 6) uniform image2D u_varianceImage;
  21. #endif
  22. layout(std430, push_constant, row_major) uniform b_pc
  23. {
  24. Mat4 u_invProjMat;
  25. };
  26. const I32 CONVOLUTION_RADIUS = 2;
  27. const F32 KERNEL_WEIGHTS[CONVOLUTION_RADIUS + 1] = F32[3](1.0, 2.0 / 3.0, 1.0 / 6.0);
  28. Vec3 toViewspace(Vec2 uv, F32 depth)
  29. {
  30. const Vec4 pos4 = u_invProjMat * Vec4(UV_TO_NDC(uv), depth, 1.0);
  31. const Vec3 pos = pos4.xyz / pos4.w;
  32. return pos;
  33. }
  34. F32 computeShadowsLuma(F32 shadowLayers[MAX_RT_SHADOW_LAYERS])
  35. {
  36. F32 l = 0.0;
  37. ANKI_UNROLL for(U32 i = 0u; i < MAX_RT_SHADOW_LAYERS; ++i)
  38. {
  39. l += shadowLayers[i];
  40. }
  41. return l;
  42. }
  43. F32 computeVarianceCenter(Vec2 uv)
  44. {
  45. const F32 kernel[2][2] = {{1.0 / 4.0, 1.0 / 8.0}, {1.0 / 8.0, 1.0 / 16.0}};
  46. const I32 radius = 1;
  47. const Vec2 texelSize = 1.0 / Vec2(textureSize(u_varianceTex, 0).xy);
  48. F32 sum = 0.0;
  49. for(I32 yy = -radius; yy <= radius; yy++)
  50. {
  51. for(I32 xx = -radius; xx <= radius; xx++)
  52. {
  53. const Vec2 newUv = uv + Vec2(xx, yy) * texelSize;
  54. const F32 k = kernel[abs(xx)][abs(yy)];
  55. sum += textureLod(u_varianceTex, u_linearAnyClampSampler, newUv, 0.0).r * k;
  56. }
  57. }
  58. return sum;
  59. }
  60. void main()
  61. {
  62. if(skipOutOfBoundsInvocations(WORKGROUP_SIZE, FB_SIZE))
  63. {
  64. return;
  65. }
  66. const Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(FB_SIZE);
  67. const F32 depth = textureLod(u_depthTex, u_linearAnyClampSampler, uv, 0.0).r;
  68. if(depth == 1.0)
  69. {
  70. // Sky
  71. imageStore(u_shadowsImage, IVec2(gl_GlobalInvocationID), UVec4(0));
  72. #if !LAST_PASS
  73. imageStore(u_varianceImage, IVec2(gl_GlobalInvocationID), Vec4(0.0));
  74. #endif
  75. return;
  76. }
  77. // Set the reference sample
  78. const F32 depthCenter = depth;
  79. const Vec3 positionCenter = toViewspace(uv, depthCenter);
  80. // Read center luma
  81. F32 shadowLayers[MAX_RT_SHADOW_LAYERS];
  82. unpackRtShadows(textureLod(u_shadowsTex, u_nearestAnyClampSampler, uv, 0.0), shadowLayers);
  83. const F32 refLuma = computeShadowsLuma(shadowLayers);
  84. // Center variance
  85. const F32 varianceCenter = computeVarianceCenter(uv);
  86. // Init the sums
  87. F32 sumShadowLayers[MAX_RT_SHADOW_LAYERS];
  88. zeroRtShadowLayers(sumShadowLayers);
  89. F32 sumVariance = 0.0;
  90. F32 sumWeight = 0.0;
  91. // Convolve
  92. const Vec2 texelSize = 1.0 / Vec2(textureSize(u_shadowsTex, 0).xy);
  93. for(I32 offsetx = -CONVOLUTION_RADIUS; offsetx <= CONVOLUTION_RADIUS; offsetx++)
  94. {
  95. for(I32 offsety = -CONVOLUTION_RADIUS; offsety <= CONVOLUTION_RADIUS; offsety++)
  96. {
  97. const Vec2 sampleUv = uv + Vec2(offsetx, offsety) * texelSize;
  98. // Read shadows
  99. F32 shadowLayers[MAX_RT_SHADOW_LAYERS];
  100. unpackRtShadows(textureLod(u_shadowsTex, u_nearestAnyClampSampler, sampleUv, 0.0), shadowLayers);
  101. // Compute luma weight
  102. const F32 luma = computeShadowsLuma(shadowLayers);
  103. const F32 variance = textureLod(u_varianceTex, u_linearAnyClampSampler, sampleUv, 0.0).x;
  104. const F32 sigmaL = 4.0;
  105. const F32 lumaDiff = abs(luma - refLuma);
  106. const F32 wl = min(1.0, exp(-lumaDiff / (sigmaL * sqrt(varianceCenter + 0.001) + EPSILON)));
  107. // Set the current sample
  108. const F32 depthTap = textureLod(u_depthTex, u_linearAnyClampSampler, sampleUv, 0.0).r;
  109. const Vec3 positionTap = toViewspace(sampleUv, depthTap);
  110. // Do bilateral
  111. F32 w = calculateBilateralWeightViewspacePosition(positionCenter, positionTap, 0.5);
  112. // Include more weights
  113. w *= wl;
  114. // w *= KERNEL_WEIGHTS[abs(offsetx)] * KERNEL_WEIGHTS[abs(offsety)];
  115. // Sum
  116. ANKI_UNROLL for(U32 i = 0u; i < MAX_RT_SHADOW_LAYERS; ++i)
  117. {
  118. sumShadowLayers[i] += shadowLayers[i] * w;
  119. }
  120. sumVariance += w * w * variance;
  121. sumWeight += w;
  122. }
  123. }
  124. // Normalize
  125. sumWeight += EPSILON;
  126. ANKI_UNROLL for(U32 i = 0u; i < MAX_RT_SHADOW_LAYERS; ++i)
  127. {
  128. sumShadowLayers[i] /= sumWeight;
  129. }
  130. sumVariance /= (sumWeight * sumWeight);
  131. // Store
  132. imageStore(u_shadowsImage, IVec2(gl_GlobalInvocationID), packRtShadows(sumShadowLayers));
  133. #if !LAST_PASS
  134. imageStore(u_varianceImage, IVec2(gl_GlobalInvocationID), Vec4(sumVariance, 0.0, 0.0, 0.0));
  135. #endif
  136. }
  137. #pragma anki end