SsgiReconstruct.ankiprog 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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. // The VARIANT points to the master fragment in the quad:
  6. // -----
  7. // |3|2|
  8. // |0|1|
  9. // -----
  10. #pragma anki mutator VARIANT 0 1 2 3
  11. ANKI_SPECIALIZATION_CONSTANT_UVEC2(FB_SIZE, 0, UVec2(1));
  12. #pragma anki start comp
  13. #include <shaders/Common.glsl>
  14. const UVec2 WORKGROUP_SIZE = UVec2(16u, 16u);
  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_linearAnyClampSampler;
  17. layout(set = 0, binding = 1) uniform texture2D u_inTex;
  18. layout(set = 0, binding = 2) uniform texture2D u_depthTex;
  19. layout(set = 0, binding = 3) writeonly uniform image2D u_outImg;
  20. shared Vec3 s_colors[WORKGROUP_SIZE.y][WORKGROUP_SIZE.x];
  21. shared Vec4 s_depths[WORKGROUP_SIZE.y][WORKGROUP_SIZE.x];
  22. F32 computeDepthWeights(F32 refDepth, F32 depth)
  23. {
  24. const F32 diff = abs(refDepth - depth);
  25. const F32 weight = sqrt(1.0 / (EPSILON + diff));
  26. return weight;
  27. }
  28. void reconstruct(IVec2 storeCoord, F32 depthRef, Vec4 colorAndDepth0, Vec4 colorAndDepth1)
  29. {
  30. F32 weight = computeDepthWeights(depthRef, colorAndDepth0.w);
  31. Vec3 col = colorAndDepth0.rgb * weight;
  32. F32 weightSum = weight;
  33. weight = computeDepthWeights(depthRef, colorAndDepth1.w);
  34. col += colorAndDepth1.rgb * weight;
  35. weightSum += weight;
  36. col /= weightSum;
  37. imageStore(u_outImg, storeCoord, Vec4(col, 0.0));
  38. }
  39. void reconstructAll(Vec4 depthRefs, Vec3 masterColor)
  40. {
  41. const IVec2 localInvocationId = IVec2(gl_LocalInvocationID.xy);
  42. #if VARIANT == 0
  43. const IVec2 masterStoreCoord = IVec2(gl_GlobalInvocationID.xy * 2);
  44. const IVec2 slaveRelativeCoords[3] = IVec2[](IVec2(1, 0), IVec2(1, 1), IVec2(0, 1));
  45. const U32 masterDrefIdx = 3;
  46. const U32 slaveDrefIdx[3] = U32[](2, 1, 0);
  47. #elif VARIANT == 1
  48. const IVec2 masterStoreCoord = IVec2(gl_GlobalInvocationID.xy * 2) + IVec2(1, 0);
  49. const IVec2 slaveRelativeCoords[3] = IVec2[](IVec2(-1, 0), IVec2(0, 1), IVec2(-1, 1));
  50. const U32 masterDrefIdx = 2;
  51. const U32 slaveDrefIdx[3] = U32[](3, 1, 0);
  52. #elif VARIANT == 2
  53. const IVec2 masterStoreCoord = IVec2(gl_GlobalInvocationID.xy * 2) + IVec2(1, 1);
  54. const IVec2 slaveRelativeCoords[3] = IVec2[](IVec2(-1, -1), IVec2(0, -1), IVec2(-1, 0));
  55. const U32 masterDrefIdx = 1;
  56. const U32 slaveDrefIdx[3] = U32[](3, 2, 0);
  57. #else
  58. const IVec2 masterStoreCoord = IVec2(gl_GlobalInvocationID.xy * 2) + IVec2(0, 1);
  59. const IVec2 slaveRelativeCoords[3] = IVec2[](IVec2(0, -1), IVec2(1, -1), IVec2(1, 0));
  60. const U32 masterDrefIdx = 0;
  61. const U32 slaveDrefIdx[3] = U32[](3, 2, 1);
  62. #endif
  63. const Vec4 masterColorAndDepth = Vec4(masterColor, depthRefs[masterDrefIdx]);
  64. imageStore(u_outImg, masterStoreCoord, Vec4(masterColor, 0.0));
  65. ANKI_UNROLL for(U32 i = 0; i < 3; ++i)
  66. {
  67. const IVec2 sharedCoord =
  68. clamp(localInvocationId + slaveRelativeCoords[i], IVec2(0), IVec2(WORKGROUP_SIZE) - 1);
  69. const Vec3 masterColor2 = s_colors[sharedCoord.y][sharedCoord.x];
  70. const F32 masterDepth2 = s_depths[sharedCoord.y][sharedCoord.x][masterDrefIdx];
  71. const IVec2 storeCoord = masterStoreCoord + slaveRelativeCoords[i];
  72. reconstruct(storeCoord, depthRefs[slaveDrefIdx[i]], masterColorAndDepth, Vec4(masterColor2, masterDepth2));
  73. }
  74. }
  75. void main()
  76. {
  77. const UVec2 IN_TEXTURE_SIZE = FB_SIZE / 2;
  78. // Initialize the storage for all threads, including helpers. The check should be a constexpr
  79. if((WORKGROUP_SIZE.x % IN_TEXTURE_SIZE.x) != 0 || (WORKGROUP_SIZE.y % IN_TEXTURE_SIZE.y) != 0)
  80. {
  81. s_colors[gl_LocalInvocationID.y][gl_LocalInvocationID.x] = Vec3(0.0);
  82. s_depths[gl_LocalInvocationID.y][gl_LocalInvocationID.x] = Vec4(1000.0); // High value so it has low weight
  83. memoryBarrierShared();
  84. barrier();
  85. }
  86. ANKI_BRANCH if(gl_GlobalInvocationID.x >= IN_TEXTURE_SIZE.x || gl_GlobalInvocationID.y >= IN_TEXTURE_SIZE.y)
  87. {
  88. // Out of bounds
  89. return;
  90. }
  91. const Vec2 inTexelSize = 1.0 / Vec2(IN_TEXTURE_SIZE);
  92. const Vec2 fbTexelSize = 1.0 / Vec2(FB_SIZE);
  93. const Vec2 inUv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(IN_TEXTURE_SIZE);
  94. const Vec2 fbUv = (Vec2(gl_GlobalInvocationID.xy) * 2.0 + 1.0) / Vec2(FB_SIZE);
  95. const Vec3 color = textureLod(u_inTex, u_linearAnyClampSampler, inUv, 0.0).rgb;
  96. const Vec4 depthRefs = textureGather(sampler2D(u_depthTex, u_linearAnyClampSampler), fbUv, 0);
  97. s_colors[gl_LocalInvocationID.y][gl_LocalInvocationID.x] = color;
  98. s_depths[gl_LocalInvocationID.y][gl_LocalInvocationID.x] = depthRefs;
  99. memoryBarrierShared();
  100. barrier();
  101. reconstructAll(depthRefs, color);
  102. }
  103. #pragma anki end