Ssgi.ankiprog 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright (C) 2009-2021, 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 fragment in the quad that will be processed:
  6. // -----
  7. // |3|2|
  8. // |0|1|
  9. // -----
  10. #pragma anki mutator VARIANT 0 1 2 3
  11. #pragma anki start comp
  12. #include <AnKi/Shaders/SsRaymarching.glsl>
  13. #include <AnKi/Shaders/Functions.glsl>
  14. #include <AnKi/Shaders/Pack.glsl>
  15. #include <AnKi/Shaders/ImportanceSampling.glsl>
  16. #include <AnKi/Shaders/Include/SsgiTypes.h>
  17. const UVec2 WORKGROUP_SIZE = UVec2(16, 16);
  18. layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
  19. layout(set = 0, binding = 0, rgba16f) uniform image2D out_img;
  20. layout(set = 0, binding = 1, row_major, std140) uniform u_
  21. {
  22. SsgiUniforms u_unis;
  23. };
  24. layout(set = 0, binding = 2) uniform sampler u_trilinearClampSampler;
  25. layout(set = 0, binding = 3) uniform texture2D u_gbufferRt2;
  26. layout(set = 0, binding = 4) uniform texture2D u_depthRt;
  27. layout(set = 0, binding = 5) uniform texture2D u_lightBufferRt;
  28. layout(set = 0, binding = 6) uniform texture2D u_historyTex;
  29. layout(set = 0, binding = 7) uniform texture2D u_motionVectorsTex;
  30. layout(set = 0, binding = 8) uniform texture2D u_motionVectorRejectionTex;
  31. void main()
  32. {
  33. // Compute a global invocation ID that takes the checkerboard pattern into account
  34. UVec2 fixedGlobalInvocationId = gl_GlobalInvocationID.xy;
  35. fixedGlobalInvocationId *= 2u;
  36. #if VARIANT == 0
  37. // Nothing
  38. #elif VARIANT == 1
  39. fixedGlobalInvocationId.x += 1u;
  40. #elif VARIANT == 2
  41. fixedGlobalInvocationId += 1u;
  42. #else
  43. fixedGlobalInvocationId.y += 1u;
  44. #endif
  45. if(fixedGlobalInvocationId.x >= u_unis.m_framebufferSize.x
  46. || fixedGlobalInvocationId.y >= u_unis.m_framebufferSize.y)
  47. {
  48. // Skip threads outside the writable image
  49. return;
  50. }
  51. const Vec2 uv = (Vec2(fixedGlobalInvocationId.xy) + 0.5) / Vec2(u_unis.m_framebufferSize);
  52. const Vec2 ndc = UV_TO_NDC(uv);
  53. // Get normal
  54. const Vec3 worldNormal = readNormalFromGBuffer(u_gbufferRt2, u_trilinearClampSampler, uv);
  55. const Vec3 viewNormal = u_unis.m_normalMat * worldNormal;
  56. // Get depth
  57. const F32 depth = textureLod(u_depthRt, u_trilinearClampSampler, uv, 0.0).r;
  58. // Compute view pos
  59. const Vec4 viewPos4 = u_unis.m_invProjMat * Vec4(ndc, depth, 1.0);
  60. const Vec3 viewPos = viewPos4.xyz / viewPos4.w;
  61. // Get a random point inside the hemisphere. Use hemisphereSampleCos to avoid perpendicular vecs to viewNormal
  62. const UVec2 random = rand3DPCG16(UVec3(gl_GlobalInvocationID.xy, u_unis.m_frameCount)).xy;
  63. Vec2 randomCircle = hammersleyRandom16(0u, 0xFFFFu, random);
  64. randomCircle.x *= 0.85; // Reduce the cone angle a bit to avoid self-collisions
  65. const Vec3 randomHemisphere = rotationFromDirection(viewNormal) * hemisphereSampleCos(randomCircle);
  66. // Trace
  67. Vec3 hitPoint;
  68. F32 hitAttenuation;
  69. const U32 lod = 0u;
  70. const F32 minStepf = 4.0;
  71. const F32 noise = F32(random.x) * (1.0 / 65536.0);
  72. raymarchGroundTruth(viewPos, randomHemisphere, uv, depth, u_unis.m_projMat, u_unis.m_maxSteps, u_depthRt,
  73. u_trilinearClampSampler, F32(lod), u_unis.m_depthBufferSize, u_unis.m_firstStepPixels,
  74. U32(mix(minStepf, F32(u_unis.m_firstStepPixels), noise)), hitPoint, hitAttenuation);
  75. // Reject backfacing
  76. ANKI_BRANCH if(hitAttenuation > 0.0)
  77. {
  78. const Vec3 hitNormal =
  79. u_unis.m_normalMat * readNormalFromGBuffer(u_gbufferRt2, u_trilinearClampSampler, hitPoint.xy);
  80. F32 backFaceAttenuation;
  81. rejectBackFaces(randomHemisphere, hitNormal, backFaceAttenuation);
  82. hitAttenuation *= backFaceAttenuation;
  83. }
  84. // Read the light buffer
  85. Vec3 outColor;
  86. ANKI_BRANCH if(hitAttenuation > 0.0)
  87. {
  88. // Reproject the UV because you are reading the previous frame
  89. const Vec4 v4 = u_unis.m_prevViewProjMatMulInvViewProjMat * Vec4(UV_TO_NDC(hitPoint.xy), hitPoint.z, 1.0);
  90. hitPoint.xy = NDC_TO_UV(v4.xy / v4.w);
  91. // Read the light buffer
  92. outColor = textureLod(u_lightBufferRt, u_trilinearClampSampler, hitPoint.xy, 100.0).rgb;
  93. outColor = clamp(outColor, 0.0, FLT_MAX); // Fix the value just in case
  94. outColor *= hitAttenuation;
  95. #if 0
  96. // Compute a new normal based on the new hit point
  97. const F32 depth = textureLod(u_depthRt, u_trilinearClampSampler, hitPoint.xy, 0.0).r;
  98. const Vec4 viewPos4 = u_unis.m_invProjMat * Vec4(UV_TO_NDC(hitPoint.xy), depth, 1.0);
  99. const Vec3 hitViewPos = viewPos4.xyz / viewPos4.w;
  100. const Vec3 newViewNormal = normalize(hitViewPos - viewPos);
  101. #else
  102. const Vec3 newViewNormal = viewNormal;
  103. #endif
  104. // Modulate
  105. const F32 NoL = max(0.0, dot(randomHemisphere, newViewNormal));
  106. outColor *= NoL;
  107. outColor *= 2.0 * PI;
  108. }
  109. else
  110. {
  111. outColor = Vec3(0.0, 0.0, 0.0);
  112. }
  113. // Blend with history
  114. {
  115. const Vec2 historyUv = uv + textureLod(u_motionVectorsTex, u_trilinearClampSampler, uv, 0.0).rg;
  116. const F32 rejection = textureLod(u_motionVectorRejectionTex, u_trilinearClampSampler, uv, 0.0).r;
  117. const Vec3 history = textureLod(u_historyTex, u_trilinearClampSampler, historyUv, 0.0).rgb;
  118. const F32 MAX_BLEND = 0.05;
  119. const F32 blend = mix(MAX_BLEND, 1.0, rejection);
  120. outColor = mix(history, outColor, blend);
  121. }
  122. // Remove fireflies
  123. #if 0
  124. const Vec3 avgColor = subgroupAdd(outColor) / F32(gl_SubgroupSize);
  125. outColor = min(outColor, avgColor);
  126. #endif
  127. // Store
  128. imageStore(out_img, IVec2(gl_GlobalInvocationID.xy), Vec4(outColor, 1.0));
  129. }
  130. #pragma anki end