TemporalAAResolve.ankiprog 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright (C) 2009-2020, 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 SHARPEN 0 1 2 // 0: disabled, 1: vertical, 2: horizontal
  6. #pragma anki mutator VARIANCE_CLIPPING 0 1
  7. #pragma anki mutator TONEMAP_FIX 0 1
  8. #pragma anki mutator YCBCR 0 1
  9. ANKI_SPECIALIZATION_CONSTANT_F32(VARIANCE_CLIPPING_GAMMA, 0, 1.0);
  10. ANKI_SPECIALIZATION_CONSTANT_F32(BLEND_FACTOR, 1, 0.5);
  11. ANKI_SPECIALIZATION_CONSTANT_UVEC2(FB_SIZE, 2, UVec2(1));
  12. #pragma anki start comp
  13. #include <shaders/Functions.glsl>
  14. #include <shaders/Pack.glsl>
  15. #include <shaders/Tonemapping.glsl>
  16. const UVec2 WORKGROUP_SIZE = UVec2(16, 16);
  17. layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
  18. layout(set = 0, binding = 0) uniform sampler u_linearAnyClampSampler;
  19. layout(set = 0, binding = 1) uniform texture2D u_depthRt;
  20. layout(set = 0, binding = 2) uniform texture2D u_inputRt;
  21. layout(set = 0, binding = 3) uniform texture2D u_historyRt;
  22. layout(set = 0, binding = 4) uniform texture2D u_velocityRt;
  23. layout(set = 0, binding = 5) writeonly uniform image2D out_img;
  24. #if TONEMAP_FIX
  25. # define TONEMAPPING_SET 0
  26. # define TONEMAPPING_BINDING 6
  27. # include <shaders/TonemappingResources.glsl>
  28. #endif
  29. layout(push_constant, std140, row_major) uniform pc_
  30. {
  31. Mat4 u_prevViewProjMatMulInvViewProjMat;
  32. };
  33. #if YCBCR
  34. # define sample(s, uv) rgbToYCbCr(textureLod(s, u_linearAnyClampSampler, uv, 0.0).rgb)
  35. # define sampleOffset(s, uv, x, y) \
  36. rgbToYCbCr(textureLodOffset(sampler2D(s, u_linearAnyClampSampler), uv, 0.0, IVec2(x, y)).rgb)
  37. #else
  38. # define sample(s, uv) textureLod(s, u_linearAnyClampSampler, uv, 0.0).rgb
  39. # define sampleOffset(s, uv, x, y) textureLodOffset(sampler2D(s, u_linearAnyClampSampler), uv, 0.0, IVec2(x, y)).rgb
  40. #endif
  41. #define VELOCITY 0
  42. Vec3 sharpen(Vec2 uv)
  43. {
  44. const Vec3 center = sample(u_inputRt, uv);
  45. #if SHARPEN == 1
  46. Vec3 near = sampleOffset(u_inputRt, uv, 1, 0) + sampleOffset(u_inputRt, uv, -1, 0);
  47. #else
  48. Vec3 near = sampleOffset(u_inputRt, uv, 0, 1) + sampleOffset(u_inputRt, uv, 0, -1);
  49. #endif
  50. near *= 0.5;
  51. const F32 sharpness = 1.0;
  52. return center + max(Vec3(0.0), center - near) * sharpness;
  53. }
  54. void main()
  55. {
  56. if((FB_SIZE.x % WORKGROUP_SIZE.x) != 0u || (FB_SIZE.y % WORKGROUP_SIZE.y) != 0u) // This check is free
  57. {
  58. if(gl_GlobalInvocationID.x >= FB_SIZE.x || gl_GlobalInvocationID.y >= FB_SIZE.y)
  59. {
  60. return;
  61. }
  62. }
  63. const Vec2 uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(FB_SIZE);
  64. const F32 depth = textureLod(u_depthRt, u_linearAnyClampSampler, uv, 0.0).r;
  65. // Get prev uv coords
  66. Vec2 oldUv;
  67. #if VELOCITY
  68. const Vec2 velocity = textureLod(u_velocityRt, u_linearAnyClampSampler, uv, 0.0).rg;
  69. if(velocity.x != -1.0)
  70. {
  71. oldUv = uv + velocity;
  72. }
  73. else
  74. #endif
  75. {
  76. const Vec4 v4 = u_prevViewProjMatMulInvViewProjMat * Vec4(UV_TO_NDC(uv), depth, 1.0);
  77. oldUv = NDC_TO_UV(v4.xy / v4.w);
  78. }
  79. // Read textures
  80. Vec3 historyCol = sample(u_historyRt, oldUv);
  81. #if SHARPEN > 0
  82. const Vec3 crntCol = sharpen(uv);
  83. #else
  84. const Vec3 crntCol = sample(u_inputRt, uv);
  85. #endif
  86. // Remove ghosting by clamping the history color to neighbour's AABB
  87. const Vec3 near0 = sampleOffset(u_inputRt, uv, 1, 0);
  88. const Vec3 near1 = sampleOffset(u_inputRt, uv, 0, 1);
  89. const Vec3 near2 = sampleOffset(u_inputRt, uv, -1, 0);
  90. const Vec3 near3 = sampleOffset(u_inputRt, uv, 0, -1);
  91. #if VARIANCE_CLIPPING
  92. const Vec3 m1 = crntCol + near0 + near1 + near2 + near3;
  93. const Vec3 m2 = crntCol * crntCol + near0 * near0 + near1 * near1 + near2 * near2 + near3 * near3;
  94. const Vec3 mu = m1 / 5.0;
  95. const Vec3 sigma = sqrt(m2 / 5.0 - mu * mu);
  96. const Vec3 boxMin = mu - VARIANCE_CLIPPING_GAMMA * sigma;
  97. const Vec3 boxMax = mu + VARIANCE_CLIPPING_GAMMA * sigma;
  98. #else
  99. const Vec3 boxMin = min(crntCol, min(near0, min(near1, min(near2, near3))));
  100. const Vec3 boxMax = max(crntCol, max(near0, max(near1, max(near2, near3))));
  101. #endif
  102. historyCol = clamp(historyCol, boxMin, boxMax);
  103. // Remove jitter (T. Lottes)
  104. #if YCBCR
  105. const F32 lum0 = crntCol.r;
  106. const F32 lum1 = historyCol.r;
  107. const F32 maxLum = boxMax.r;
  108. #elif TONEMAP_FIX
  109. const F32 lum0 = computeLuminance(tonemap(crntCol, u_exposureThreshold0));
  110. const F32 lum1 = computeLuminance(tonemap(historyCol, u_exposureThreshold0));
  111. // F32 maxLum = computeLuminance(tonemap(boxMax, u_exposureThreshold0));
  112. const F32 maxLum = 1.0;
  113. #else
  114. const F32 lum0 = computeLuminance(crntCol);
  115. const F32 lum1 = computeLuminance(historyCol);
  116. const F32 maxLum = computeLuminance(boxMax);
  117. #endif
  118. F32 diff = abs(lum0 - lum1) / max(lum0, max(lum1, maxLum + EPSILON));
  119. diff = 1.0 - diff;
  120. diff = diff * diff;
  121. const F32 feedback = mix(0.0, BLEND_FACTOR, diff);
  122. // Write result
  123. #if YCBCR
  124. const Vec3 outColor = yCbCrToRgb(mix(historyCol, crntCol, feedback));
  125. #else
  126. const Vec3 outColor = mix(historyCol, crntCol, feedback);
  127. #endif
  128. imageStore(out_img, IVec2(gl_GlobalInvocationID.xy), Vec4(outColor, 0.0));
  129. }
  130. #pragma anki end