RtShadowsDenoise.ankiprog 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright (C) 2009-2022, 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 BLUR_ORIENTATION 0 1
  6. #pragma anki start comp
  7. ANKI_SPECIALIZATION_CONSTANT_UVEC2(OUT_IMAGE_SIZE, 0u);
  8. ANKI_SPECIALIZATION_CONSTANT_U32(MIN_SAMPLE_COUNT, 2u);
  9. ANKI_SPECIALIZATION_CONSTANT_U32(MAX_SAMPLE_COUNT, 3u);
  10. #include <AnKi/Shaders/BilateralFilter.glsl>
  11. #include <AnKi/Shaders/PackFunctions.glsl>
  12. #include <AnKi/Shaders/RtShadows.glsl>
  13. #include <AnKi/Shaders/Functions.glsl>
  14. const UVec2 WORKGROUP_SIZE = UVec2(8u, 8u);
  15. layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
  16. layout(set = 0, binding = 0) uniform sampler u_nearestAnyClampSampler;
  17. layout(set = 0, binding = 1) uniform sampler u_linearAnyClampSampler;
  18. layout(set = 0, binding = 2) uniform utexture2D u_inTex;
  19. layout(set = 0, binding = 3) uniform texture2D u_depthTex;
  20. layout(set = 0, binding = 4) uniform texture2D u_gbuffer2Tex;
  21. layout(set = 0, binding = 5) uniform texture2D u_momentsTex;
  22. layout(set = 0, binding = 6) uniform texture2D u_historyLengthTex;
  23. layout(set = 0, binding = 7) writeonly uniform uimage2D u_outImg;
  24. layout(push_constant, row_major, std140) uniform b_pc
  25. {
  26. RtShadowsDenoiseUniforms u_unis;
  27. };
  28. Vec3 unproject(Vec2 ndc, F32 depth)
  29. {
  30. const Vec4 worldPos4 = u_unis.invViewProjMat * Vec4(ndc, depth, 1.0);
  31. const Vec3 worldPos = worldPos4.xyz / worldPos4.w;
  32. return worldPos;
  33. }
  34. F32 computeVarianceCenter(Vec2 uv)
  35. {
  36. const F32 kernel[2][2] = {{1.0 / 4.0, 1.0 / 8.0}, {1.0 / 8.0, 1.0 / 16.0}};
  37. const I32 radius = 1;
  38. const Vec2 texelSize = 1.0 / Vec2(textureSize(u_momentsTex, 0).xy);
  39. Vec2 sumMoments = Vec2(0.0);
  40. for(I32 yy = -radius; yy <= radius; yy++)
  41. {
  42. for(I32 xx = -radius; xx <= radius; xx++)
  43. {
  44. const Vec2 newUv = uv + Vec2(xx, yy) * texelSize;
  45. const F32 k = kernel[abs(xx)][abs(yy)];
  46. sumMoments += textureLod(u_momentsTex, u_linearAnyClampSampler, newUv, 0.0).xy * k;
  47. }
  48. }
  49. return abs(sumMoments.y - sumMoments.x * sumMoments.x);
  50. }
  51. void main()
  52. {
  53. if(skipOutOfBoundsInvocations(WORKGROUP_SIZE, OUT_IMAGE_SIZE))
  54. {
  55. return;
  56. }
  57. const Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(OUT_IMAGE_SIZE);
  58. // Reference
  59. const F32 depthCenter = textureLod(u_depthTex, u_linearAnyClampSampler, uv, 0.0).r;
  60. if(depthCenter == 1.0)
  61. {
  62. imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), UVec4(0));
  63. return;
  64. }
  65. const Vec3 positionCenter = unproject(UV_TO_NDC(uv), depthCenter);
  66. const Vec3 normalCenter = unpackNormalFromGBuffer(textureLod(u_gbuffer2Tex, u_linearAnyClampSampler, uv, 0.0));
  67. F32 shadowFactors[MAX_RT_SHADOW_LAYERS];
  68. unpackRtShadows(textureLod(u_inTex, u_nearestAnyClampSampler, uv, 0.0), shadowFactors);
  69. // Decide the amount of blurring
  70. const F32 varianceCenter = computeVarianceCenter(uv);
  71. const F32 historyLength =
  72. textureLod(u_historyLengthTex, u_linearAnyClampSampler, uv, 0.0).x * RT_SHADOWS_MAX_HISTORY_LENGTH;
  73. U32 sampleCount;
  74. if(historyLength < 2.0)
  75. {
  76. // Worst case
  77. sampleCount = MAX_SAMPLE_COUNT;
  78. }
  79. else if(historyLength > 4.0 && varianceCenter < 0.0001)
  80. {
  81. // Best case
  82. sampleCount = MIN_SAMPLE_COUNT;
  83. }
  84. else
  85. {
  86. // Every other case
  87. F32 blur = varianceCenter * 100.0;
  88. blur = min(1.0, blur);
  89. const F32 sampleCountf = mix(F32(MIN_SAMPLE_COUNT), F32(MAX_SAMPLE_COUNT), blur);
  90. sampleCount = U32(sampleCountf);
  91. }
  92. sampleCount = sampleCount / 2u;
  93. // Sample
  94. F32 weight = 1.0; // TODO fix that
  95. for(I32 i = -I32(sampleCount); i < I32(sampleCount); ++i)
  96. {
  97. const Vec2 texelSize = 1.0 / Vec2(OUT_IMAGE_SIZE);
  98. #if BLUR_ORIENTATION == 0
  99. const Vec2 sampleUv = Vec2(uv.x + F32(i) * texelSize.x, uv.y);
  100. #else
  101. const Vec2 sampleUv = Vec2(uv.x, uv.y + F32(i) * texelSize.y);
  102. #endif
  103. F32 localShadowFactors[MAX_RT_SHADOW_LAYERS];
  104. unpackRtShadows(textureLod(u_inTex, u_nearestAnyClampSampler, sampleUv, 0.0), localShadowFactors);
  105. const F32 depthTap = textureLod(u_depthTex, u_linearAnyClampSampler, sampleUv, 0.0).r;
  106. const Vec3 positionTap = unproject(UV_TO_NDC(sampleUv), depthTap);
  107. const Vec3 normalTap =
  108. unpackNormalFromGBuffer(textureLod(u_gbuffer2Tex, u_linearAnyClampSampler, sampleUv, 0.0));
  109. // F32 w = calculateBilateralWeighPlane(depthCenter, depthTap, 1.0);
  110. F32 w = calculateBilateralWeightPlane(positionCenter, normalCenter, positionTap, normalTap, 1.0);
  111. w *= gaussianWeight(0.4, abs(F32(i)) / F32(sampleCount + 1u));
  112. ANKI_UNROLL for(U32 i = 0u; i < MAX_RT_SHADOW_LAYERS; ++i)
  113. {
  114. shadowFactors[i] += localShadowFactors[i] * w;
  115. }
  116. weight += w;
  117. }
  118. // Write value
  119. ANKI_UNROLL for(U32 i = 0u; i < MAX_RT_SHADOW_LAYERS; ++i)
  120. {
  121. shadowFactors[i] /= weight;
  122. }
  123. imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), packRtShadows(shadowFactors));
  124. }
  125. #pragma anki end