RtShadowsDenoise.ankiprog 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright (C) 2009-present, 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 technique comp
  7. #include <AnKi/Shaders/BilateralFilter.hlsl>
  8. #include <AnKi/Shaders/PackFunctions.hlsl>
  9. #include <AnKi/Shaders/RtShadows.hlsl>
  10. #include <AnKi/Shaders/Functions.hlsl>
  11. SamplerState g_linearAnyClampSampler : register(s0);
  12. Texture2D<Vec4> g_inTex : register(t0);
  13. Texture2D<Vec4> g_depthTex : register(t1);
  14. Texture2D<Vec4> g_gbuffer2Tex : register(t2);
  15. Texture2D<Vec4> g_momentsTex : register(t3);
  16. Texture2D<Vec4> g_historyLengthTex : register(t4);
  17. RWTexture2D<Vec4> g_storageTex : register(u0);
  18. ANKI_FAST_CONSTANTS(RtShadowsDenoiseConstants, g_consts)
  19. Vec3 unproject(Vec2 ndc, F32 depth)
  20. {
  21. const Vec4 worldPos4 = mul(g_consts.m_invViewProjMat, Vec4(ndc, depth, 1.0));
  22. const Vec3 worldPos = worldPos4.xyz / worldPos4.w;
  23. return worldPos;
  24. }
  25. F32 computeVarianceCenter(Vec2 uv)
  26. {
  27. const F32 kernel[2][2] = {{1.0 / 4.0, 1.0 / 8.0}, {1.0 / 8.0, 1.0 / 16.0}};
  28. const I32 radius = 1;
  29. Vec2 texSize;
  30. F32 mipCount;
  31. g_momentsTex.GetDimensions(0, texSize.x, texSize.y, mipCount);
  32. const Vec2 texelSize = 1.0 / texSize;
  33. Vec2 sumMoments = 0.0f;
  34. for(I32 yy = -radius; yy <= radius; yy++)
  35. {
  36. for(I32 xx = -radius; xx <= radius; xx++)
  37. {
  38. const Vec2 newUv = uv + Vec2(xx, yy) * texelSize;
  39. const F32 k = kernel[abs(xx)][abs(yy)];
  40. sumMoments += g_momentsTex.SampleLevel(g_linearAnyClampSampler, newUv, 0.0).xy * k;
  41. }
  42. }
  43. return abs(sumMoments.y - sumMoments.x * sumMoments.x);
  44. }
  45. [numthreads(8, 8, 1)] void main(UVec3 svDispatchThreadId : SV_DISPATCHTHREADID)
  46. {
  47. Vec2 outImageSize;
  48. g_storageTex.GetDimensions(outImageSize.x, outImageSize.y);
  49. if(any(svDispatchThreadId.xy >= UVec2(outImageSize)))
  50. {
  51. return;
  52. }
  53. const Vec2 uv = (Vec2(svDispatchThreadId.xy) + 0.5) / outImageSize;
  54. // Reference
  55. const F32 depthCenter = g_depthTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).r;
  56. if(depthCenter == 1.0)
  57. {
  58. g_storageTex[svDispatchThreadId.xy] = 0.0;
  59. return;
  60. }
  61. const Vec3 positionCenter = unproject(uvToNdc(uv), depthCenter);
  62. const Vec3 normalCenter = unpackNormalFromGBuffer(g_gbuffer2Tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0));
  63. // Decide the amount of blurring
  64. const F32 varianceCenter = computeVarianceCenter(uv);
  65. const F32 historyLength = g_historyLengthTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).x * kRtShadowsMaxHistoryLength;
  66. U32 sampleCount;
  67. if(historyLength < 2.0)
  68. {
  69. // Worst case
  70. sampleCount = g_consts.m_maxSampleCount;
  71. }
  72. else if(historyLength > 4.0 && varianceCenter < 0.0001)
  73. {
  74. // Best case
  75. sampleCount = g_consts.m_minSampleCount;
  76. }
  77. else
  78. {
  79. // Every other case
  80. F32 blur = varianceCenter * 100.0;
  81. blur = min(1.0, blur);
  82. const F32 sampleCountf = lerp(F32(g_consts.m_minSampleCount), F32(g_consts.m_maxSampleCount), blur);
  83. sampleCount = U32(sampleCountf);
  84. }
  85. sampleCount = sampleCount / 2u;
  86. // Sample
  87. F32 weight = kEpsilonF32;
  88. F32 shadowFactor = 0.0;
  89. for(I32 i = -I32(sampleCount); i < I32(sampleCount); ++i)
  90. {
  91. const Vec2 texelSize = 1.0 / outImageSize;
  92. #if BLUR_ORIENTATION == 0
  93. const Vec2 sampleUv = Vec2(uv.x + F32(i) * texelSize.x, uv.y);
  94. #else
  95. const Vec2 sampleUv = Vec2(uv.x, uv.y + F32(i) * texelSize.y);
  96. #endif
  97. const F32 localShadowFactor = g_inTex.SampleLevel(g_linearAnyClampSampler, sampleUv, 0.0).r;
  98. const F32 depthTap = g_depthTex.SampleLevel(g_linearAnyClampSampler, sampleUv, 0.0).r;
  99. const Vec3 positionTap = unproject(uvToNdc(sampleUv), depthTap);
  100. const Vec3 normalTap = unpackNormalFromGBuffer(g_gbuffer2Tex.SampleLevel(g_linearAnyClampSampler, sampleUv, 0.0));
  101. // F32 localWeight = calculateBilateralWeighPlane(depthCenter, depthTap, 1.0);
  102. F32 localWeight = calculateBilateralWeightPlane(positionCenter, normalCenter, positionTap, normalTap, 1.0);
  103. localWeight *= gaussianWeight(0.4f, abs(F32(i)) / F32(sampleCount + 1u));
  104. shadowFactor += localShadowFactor * localWeight;
  105. weight += localWeight;
  106. }
  107. // Normalize and write
  108. shadowFactor /= weight;
  109. g_storageTex[svDispatchThreadId.xy] = shadowFactor;
  110. }