TemporalAA.glsl 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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 VARIANCE_CLIPPING 0 1
  6. #pragma anki mutator YCBCR 0 1
  7. ANKI_SPECIALIZATION_CONSTANT_F32(VARIANCE_CLIPPING_GAMMA, 0u);
  8. ANKI_SPECIALIZATION_CONSTANT_F32(BLEND_FACTOR, 1u);
  9. ANKI_SPECIALIZATION_CONSTANT_UVEC2(FB_SIZE, 2u);
  10. #include <AnKi/Shaders/Functions.glsl>
  11. #include <AnKi/Shaders/PackFunctions.glsl>
  12. #include <AnKi/Shaders/TonemappingFunctions.glsl>
  13. layout(set = 0, binding = 0) uniform sampler u_linearAnyClampSampler;
  14. layout(set = 0, binding = 1) uniform texture2D u_depthRt;
  15. layout(set = 0, binding = 2) uniform ANKI_RP texture2D u_inputRt;
  16. layout(set = 0, binding = 3) uniform ANKI_RP texture2D u_historyRt;
  17. layout(set = 0, binding = 4) uniform texture2D u_motionVectorsTex;
  18. const U32 TONEMAPPING_SET = 0u;
  19. const U32 TONEMAPPING_BINDING = 5u;
  20. #include <AnKi/Shaders/TonemappingResources.glsl>
  21. #if defined(ANKI_COMPUTE_SHADER)
  22. layout(set = 0, binding = 6) writeonly uniform image2D u_outImg;
  23. layout(set = 0, binding = 7) writeonly uniform image2D u_tonemappedImg;
  24. const UVec2 WORKGROUP_SIZE = UVec2(8, 8);
  25. layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
  26. #else
  27. layout(location = 0) in Vec2 in_uv;
  28. layout(location = 0) out Vec3 out_color;
  29. layout(location = 1) out Vec3 out_tonemappedColor;
  30. #endif
  31. #if YCBCR
  32. # define sample(s, uv) rgbToYCbCr(textureLod(s, u_linearAnyClampSampler, uv, 0.0).rgb)
  33. # define sampleOffset(s, uv, x, y) \
  34. rgbToYCbCr(textureLodOffset(sampler2D(s, u_linearAnyClampSampler), uv, 0.0, IVec2(x, y)).rgb)
  35. #else
  36. # define sample(s, uv) textureLod(s, u_linearAnyClampSampler, uv, 0.0).rgb
  37. # define sampleOffset(s, uv, x, y) textureLodOffset(sampler2D(s, u_linearAnyClampSampler), uv, 0.0, IVec2(x, y)).rgb
  38. #endif
  39. void main()
  40. {
  41. #if defined(ANKI_COMPUTE_SHADER)
  42. if(skipOutOfBoundsInvocations(WORKGROUP_SIZE, FB_SIZE))
  43. {
  44. return;
  45. }
  46. const Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(FB_SIZE);
  47. #else
  48. const Vec2 uv = in_uv;
  49. #endif
  50. const F32 depth = textureLod(u_depthRt, u_linearAnyClampSampler, uv, 0.0).r;
  51. // Get prev uv coords
  52. const Vec2 oldUv = uv + textureLod(u_motionVectorsTex, u_linearAnyClampSampler, uv, 0.0).rg;
  53. // Read textures
  54. Vec3 historyCol = sample(u_historyRt, oldUv);
  55. const Vec3 crntCol = sample(u_inputRt, uv);
  56. // Remove ghosting by clamping the history color to neighbour's AABB
  57. const Vec3 near0 = sampleOffset(u_inputRt, uv, 1, 0);
  58. const Vec3 near1 = sampleOffset(u_inputRt, uv, 0, 1);
  59. const Vec3 near2 = sampleOffset(u_inputRt, uv, -1, 0);
  60. const Vec3 near3 = sampleOffset(u_inputRt, uv, 0, -1);
  61. #if VARIANCE_CLIPPING
  62. const Vec3 m1 = crntCol + near0 + near1 + near2 + near3;
  63. const Vec3 m2 = crntCol * crntCol + near0 * near0 + near1 * near1 + near2 * near2 + near3 * near3;
  64. const Vec3 mu = m1 / 5.0;
  65. const Vec3 sigma = sqrt(m2 / 5.0 - mu * mu);
  66. const Vec3 boxMin = mu - VARIANCE_CLIPPING_GAMMA * sigma;
  67. const Vec3 boxMax = mu + VARIANCE_CLIPPING_GAMMA * sigma;
  68. #else
  69. const Vec3 boxMin = min(crntCol, min(near0, min(near1, min(near2, near3))));
  70. const Vec3 boxMax = max(crntCol, max(near0, max(near1, max(near2, near3))));
  71. #endif
  72. historyCol = clamp(historyCol, boxMin, boxMax);
  73. // Remove jitter (T. Lottes)
  74. #if YCBCR
  75. const F32 lum0 = crntCol.r;
  76. const F32 lum1 = historyCol.r;
  77. const F32 maxLum = boxMax.r;
  78. #else
  79. const F32 lum0 = computeLuminance(reinhardTonemap(crntCol));
  80. const F32 lum1 = computeLuminance(reinhardTonemap(historyCol));
  81. const F32 maxLum = 1.0;
  82. #endif
  83. F32 diff = abs(lum0 - lum1) / max(lum0, max(lum1, maxLum + EPSILON));
  84. diff = 1.0 - diff;
  85. diff = diff * diff;
  86. const F32 feedback = mix(0.0, BLEND_FACTOR, diff);
  87. // Write result
  88. Vec3 outColor = mix(historyCol, crntCol, feedback);
  89. #if YCBCR
  90. outColor = yCbCrToRgb(outColor);
  91. #endif
  92. const Vec3 tonemapped = linearToSRgb(tonemap(outColor, readExposureAndAverageLuminance().x));
  93. #if defined(ANKI_COMPUTE_SHADER)
  94. imageStore(u_outImg, IVec2(gl_GlobalInvocationID.xy), Vec4(outColor, 0.0));
  95. imageStore(u_tonemappedImg, IVec2(gl_GlobalInvocationID.xy), Vec4(tonemapped, 0.0));
  96. #else
  97. out_color = outColor;
  98. out_tonemappedColor = tonemapped;
  99. #endif
  100. }