Ssr.ankiprog 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. // if VARIANT==0 then the checkerboard pattern is (render on 'v'):
  6. // -----
  7. // |v| |
  8. // | |v|
  9. // -----
  10. #pragma anki mutator VARIANT 0 1
  11. #define EXTRA_REJECTION 0
  12. #pragma anki start comp
  13. #include <AnKi/Shaders/Functions.glsl>
  14. #include <AnKi/Shaders/Pack.glsl>
  15. #include <AnKi/Shaders/Include/SsrTypes.h>
  16. #include <AnKi/Shaders/Tonemapping.glsl>
  17. #include <AnKi/Shaders/SsRaymarching.glsl>
  18. const UVec2 WORKGROUP_SIZE = UVec2(16, 16);
  19. layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
  20. layout(set = 0, binding = 0, rgba16f) uniform image2D out_img;
  21. layout(set = 0, binding = 1, row_major) uniform u_
  22. {
  23. SsrUniforms u_unis;
  24. };
  25. layout(set = 0, binding = 2) uniform sampler u_trilinearClampSampler;
  26. layout(set = 0, binding = 3) uniform texture2D u_gbufferRt1;
  27. layout(set = 0, binding = 4) uniform texture2D u_gbufferRt2;
  28. layout(set = 0, binding = 5) uniform texture2D u_depthRt;
  29. layout(set = 0, binding = 6) uniform texture2D u_lightBufferRt;
  30. layout(set = 0, binding = 7) uniform sampler u_trilinearRepeatSampler;
  31. layout(set = 0, binding = 8) uniform texture2D u_noiseTex;
  32. const Vec2 NOISE_TEX_SIZE = Vec2(16.0);
  33. void main()
  34. {
  35. // Compute a global invocation ID that takes the checkerboard pattern into account
  36. IVec2 fixedGlobalInvocationId = IVec2(gl_GlobalInvocationID.xy);
  37. fixedGlobalInvocationId.x *= 2;
  38. #if VARIANT == 0
  39. fixedGlobalInvocationId.x += ((fixedGlobalInvocationId.y + 1) & 1);
  40. #else
  41. fixedGlobalInvocationId.x += ((fixedGlobalInvocationId.y + 0) & 1);
  42. #endif
  43. if(fixedGlobalInvocationId.x >= I32(u_unis.m_framebufferSize.x)
  44. || fixedGlobalInvocationId.y >= I32(u_unis.m_framebufferSize.y))
  45. {
  46. // Skip threads outside the writable image
  47. return;
  48. }
  49. const Vec2 uv = (Vec2(fixedGlobalInvocationId.xy) + 0.5) / Vec2(u_unis.m_framebufferSize);
  50. // Read part of the G-buffer
  51. const F32 roughness = readRoughnessFromGBuffer(u_gbufferRt1, u_trilinearClampSampler, uv);
  52. const Vec3 worldNormal = readNormalFromGBuffer(u_gbufferRt2, u_trilinearClampSampler, uv);
  53. // Get depth
  54. const F32 depth = textureLod(u_depthRt, u_trilinearClampSampler, uv, 0.0).r;
  55. // Get view pos
  56. const Vec4 viewPos4 = u_unis.m_invProjMat * Vec4(UV_TO_NDC(uv), depth, 1.0);
  57. const Vec3 viewPos = viewPos4.xyz / viewPos4.w;
  58. // Compute refl vector
  59. const Vec3 viewDir = normalize(viewPos);
  60. const Vec3 viewNormal = u_unis.m_normalMat * worldNormal;
  61. const Vec3 reflVec = reflect(viewDir, viewNormal);
  62. // Rand idx
  63. const Vec2 noiseUv = Vec2(u_unis.m_framebufferSize) / NOISE_TEX_SIZE * uv;
  64. const Vec2 noiseShift = 1.0 / NOISE_TEX_SIZE * F32(u_unis.m_frameCount % 4u);
  65. const F32 noise = textureLod(u_noiseTex, u_trilinearRepeatSampler, noiseUv + noiseShift, 0.0).r;
  66. // Do the heavy work
  67. Vec3 hitPoint;
  68. F32 hitAttenuation;
  69. const U32 lod = 0u;
  70. const U32 step = u_unis.m_firstStepPixels;
  71. const F32 stepf = F32(step);
  72. const F32 minStepf = stepf / 4.0;
  73. raymarchGroundTruth(viewPos, reflVec, uv, depth, u_unis.m_projMat, u_unis.m_maxSteps, u_depthRt,
  74. u_trilinearClampSampler, F32(lod), u_unis.m_depthBufferSize, step,
  75. U32((stepf - minStepf) * noise + minStepf), hitPoint, hitAttenuation);
  76. #if EXTRA_REJECTION
  77. // Reject backfacing
  78. ANKI_BRANCH if(hitAttenuation > 0.0)
  79. {
  80. const Vec3 hitNormal =
  81. u_unis.m_normalMat * readNormalFromGBuffer(u_gbufferRt2, u_trilinearClampSampler, hitPoint.xy);
  82. F32 backFaceAttenuation;
  83. rejectBackFaces(reflVec, hitNormal, backFaceAttenuation);
  84. hitAttenuation *= backFaceAttenuation;
  85. }
  86. // Reject far from hit point
  87. ANKI_BRANCH if(hitAttenuation > 0.0)
  88. {
  89. const F32 depth = textureLod(u_depthRt, u_trilinearClampSampler, hitPoint.xy, 0.0).r;
  90. Vec4 viewPos4 = u_unis.m_invProjMat * Vec4(UV_TO_NDC(hitPoint.xy), depth, 1.0);
  91. const F32 actualZ = viewPos4.z / viewPos4.w;
  92. viewPos4 = u_unis.m_invProjMat * Vec4(UV_TO_NDC(hitPoint.xy), hitPoint.z, 1.0);
  93. const F32 hitZ = viewPos4.z / viewPos4.w;
  94. const F32 rejectionMeters = 1.0;
  95. const F32 diff = abs(actualZ - hitZ);
  96. const F32 distAttenuation = (diff < rejectionMeters) ? 1.0 : 0.0;
  97. hitAttenuation *= distAttenuation;
  98. }
  99. #endif
  100. // Read the reflection
  101. Vec4 outColor;
  102. ANKI_BRANCH if(hitAttenuation > 0.0)
  103. {
  104. // Reproject the UV because you are reading the previous frame
  105. const Vec4 v4 = u_unis.m_prevViewProjMatMulInvViewProjMat * Vec4(UV_TO_NDC(hitPoint.xy), hitPoint.z, 1.0);
  106. hitPoint.xy = NDC_TO_UV(v4.xy / v4.w);
  107. // Compute the LOD based on the roughness
  108. const F32 lod = F32(u_unis.m_lightBufferMipCount - 1u) * roughness;
  109. // Read the light buffer
  110. outColor.rgb = textureLod(u_lightBufferRt, u_trilinearClampSampler, hitPoint.xy, lod).rgb;
  111. outColor.rgb = clamp(outColor.rgb, 0.0, FLT_MAX); // Fix the value just in case
  112. outColor.rgb *= hitAttenuation;
  113. outColor.a = 1.0 - hitAttenuation;
  114. }
  115. else
  116. {
  117. outColor = Vec4(0.0, 0.0, 0.0, 1.0);
  118. }
  119. // Store
  120. imageStore(out_img, fixedGlobalInvocationId, outColor);
  121. }
  122. #pragma anki end