RtShadowsSvgfVariance.ankiprog 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. ANKI_SPECIALIZATION_CONSTANT_UVEC2(FB_SIZE, 0u);
  6. #pragma anki start comp
  7. #include <AnKi/Shaders/RtShadows.glsl>
  8. #include <AnKi/Shaders/BilateralFilter.glsl>
  9. #include <AnKi/Shaders/Functions.glsl>
  10. const UVec2 WORKGROUP_SIZE = UVec2(8, 8);
  11. layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
  12. layout(set = 0, binding = 0) uniform sampler u_nearestAnyClampSampler;
  13. layout(set = 0, binding = 1) uniform sampler u_linearAnyClampSampler;
  14. layout(set = 0, binding = 2) uniform utexture2D u_shadowsTex;
  15. layout(set = 0, binding = 3) uniform texture2D u_momentsTex;
  16. layout(set = 0, binding = 4) uniform texture2D u_historyLengthTex;
  17. layout(set = 0, binding = 5) uniform texture2D u_depthTex;
  18. layout(set = 0, binding = 6) uniform uimage2D u_shadowsImage;
  19. layout(set = 0, binding = 7) uniform image2D u_varianceImage;
  20. layout(std430, push_constant, row_major) uniform b_pc
  21. {
  22. Mat4 u_invProjMat;
  23. };
  24. const I32 CONVOLUTION_RADIUS = 1;
  25. Vec3 toViewspace(Vec2 uv, F32 depth)
  26. {
  27. const Vec4 pos4 = u_invProjMat * Vec4(UV_TO_NDC(uv), depth, 1.0);
  28. const Vec3 pos = pos4.xyz / pos4.w;
  29. return pos;
  30. }
  31. void main()
  32. {
  33. if(skipOutOfBoundsInvocations(WORKGROUP_SIZE, FB_SIZE))
  34. {
  35. return;
  36. }
  37. const Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(FB_SIZE);
  38. const F32 depth = textureLod(u_depthTex, u_linearAnyClampSampler, uv, 0.0).r;
  39. if(depth == 1.0)
  40. {
  41. // Sky
  42. imageStore(u_shadowsImage, IVec2(gl_GlobalInvocationID), UVec4(0));
  43. imageStore(u_varianceImage, IVec2(gl_GlobalInvocationID), Vec4(0.0));
  44. return;
  45. }
  46. const F32 historyLength = textureLod(u_historyLengthTex, u_linearAnyClampSampler, uv, 0.0).r;
  47. UVec4 outPackedShadowLayers;
  48. F32 outVariance;
  49. if(historyLength < 4.0 / RT_SHADOWS_MAX_HISTORY_LENGTH)
  50. {
  51. // It's been stable less than 4 frames, need to do some work
  52. const Vec2 texelSize = 1.0 / Vec2(FB_SIZE);
  53. // Set the reference sample
  54. const F32 depthCenter = depth;
  55. const Vec3 positionCenter = toViewspace(uv, depthCenter);
  56. // Init the sums
  57. Vec2 sumMoments = Vec2(0.0);
  58. F32 sumWeight = 0.0;
  59. F32 sumShadowLayers[MAX_RT_SHADOW_LAYERS];
  60. zeroRtShadowLayers(sumShadowLayers);
  61. // Convolve
  62. for(I32 offsetx = -CONVOLUTION_RADIUS; offsetx <= CONVOLUTION_RADIUS; offsetx++)
  63. {
  64. for(I32 offsety = -CONVOLUTION_RADIUS; offsety <= CONVOLUTION_RADIUS; offsety++)
  65. {
  66. const Vec2 sampleUv = uv + Vec2(offsetx, offsety) * texelSize;
  67. // Set the current sample
  68. const F32 depthTap = textureLod(u_depthTex, u_linearAnyClampSampler, sampleUv, 0.0).r;
  69. const Vec3 positionTap = toViewspace(sampleUv, depthTap);
  70. // Do bilateral
  71. const F32 w = calculateBilateralWeightViewspacePosition(positionCenter, positionTap, 0.5);
  72. // Sum
  73. const Vec2 moments = textureLod(u_momentsTex, u_linearAnyClampSampler, sampleUv, 0.0).xy;
  74. sumMoments += moments * w;
  75. F32 shadowLayers[MAX_RT_SHADOW_LAYERS];
  76. unpackRtShadows(textureLod(u_shadowsTex, u_nearestAnyClampSampler, sampleUv, 0.0), shadowLayers);
  77. ANKI_UNROLL for(U32 i = 0u; i < MAX_RT_SHADOW_LAYERS; ++i)
  78. {
  79. sumShadowLayers[i] += shadowLayers[i] * w;
  80. }
  81. sumWeight += w;
  82. }
  83. }
  84. sumWeight += EPSILON;
  85. ANKI_UNROLL for(U32 i = 0u; i < MAX_RT_SHADOW_LAYERS; ++i)
  86. {
  87. sumShadowLayers[i] /= sumWeight;
  88. }
  89. sumMoments /= sumWeight;
  90. outPackedShadowLayers = packRtShadows(sumShadowLayers);
  91. outVariance = max(0.0, sumMoments.y - sumMoments.x * sumMoments.x);
  92. // Give the variance a boost for the first frames
  93. outVariance *= 4.0 / (historyLength * RT_SHADOWS_MAX_HISTORY_LENGTH);
  94. }
  95. else
  96. {
  97. // Stable for more that 4 frames, passthrough
  98. outPackedShadowLayers = textureLod(u_shadowsTex, u_nearestAnyClampSampler, uv, 0.0);
  99. const Vec2 moments = textureLod(u_momentsTex, u_linearAnyClampSampler, uv, 0.0).xy;
  100. outVariance = max(0.0, moments.y - moments.x * moments.x);
  101. }
  102. // Store
  103. imageStore(u_shadowsImage, IVec2(gl_GlobalInvocationID), outPackedShadowLayers);
  104. imageStore(u_varianceImage, IVec2(gl_GlobalInvocationID), Vec4(outVariance, 0.0, 0.0, 0.0));
  105. }
  106. #pragma anki end