IndirectDiffuse.glsl 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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. // Does SSGI and GI probe sampling
  6. ANKI_SPECIALIZATION_CONSTANT_U32(SAMPLE_COUNT, 6u);
  7. #define ENABLE_SSGI true
  8. #define ENABLE_PROBES true
  9. #define REMOVE_FIREFLIES false
  10. #define REPROJECT_LIGHTBUFFER false
  11. #define SSGI_PROBE_COMBINE(ssgiColor, probeColor) ((ssgiColor) + (probeColor))
  12. #include <AnKi/Shaders/Functions.glsl>
  13. #include <AnKi/Shaders/PackFunctions.glsl>
  14. #include <AnKi/Shaders/ImportanceSampling.glsl>
  15. #include <AnKi/Shaders/TonemappingFunctions.glsl>
  16. #include <AnKi/Shaders/Include/MiscRendererTypes.h>
  17. #define CLUSTERED_SHADING_SET 0u
  18. #define CLUSTERED_SHADING_UNIFORMS_BINDING 0u
  19. #define CLUSTERED_SHADING_GI_BINDING 1u
  20. #define CLUSTERED_SHADING_CLUSTERS_BINDING 3u
  21. #include <AnKi/Shaders/ClusteredShadingCommon.glsl>
  22. layout(set = 0, binding = 4) uniform sampler u_linearAnyClampSampler;
  23. layout(set = 0, binding = 5) uniform ANKI_RP texture2D u_gbufferRt2;
  24. layout(set = 0, binding = 6) uniform texture2D u_depthRt;
  25. layout(set = 0, binding = 7) uniform ANKI_RP texture2D u_lightBufferRt;
  26. layout(set = 0, binding = 8) uniform ANKI_RP texture2D u_historyTex;
  27. layout(set = 0, binding = 9) uniform texture2D u_motionVectorsTex;
  28. layout(set = 0, binding = 10) uniform ANKI_RP texture2D u_historyLengthTex;
  29. #if defined(ANKI_COMPUTE_SHADER)
  30. const UVec2 WORKGROUP_SIZE = UVec2(8, 8);
  31. layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y) in;
  32. layout(set = 0, binding = 11) writeonly uniform image2D u_outImage;
  33. #else
  34. layout(location = 0) in Vec2 in_uv;
  35. layout(location = 0) out Vec3 out_color;
  36. #endif
  37. layout(push_constant, std140) uniform b_pc
  38. {
  39. IndirectDiffuseUniforms u_unis;
  40. };
  41. Vec4 cheapProject(Vec4 point)
  42. {
  43. return projectPerspective(point, u_unis.m_projectionMat.x, u_unis.m_projectionMat.y, u_unis.m_projectionMat.z,
  44. u_unis.m_projectionMat.w);
  45. }
  46. void main()
  47. {
  48. #if defined(ANKI_COMPUTE_SHADER)
  49. if(gl_GlobalInvocationID.x >= u_unis.m_viewportSize.x || gl_GlobalInvocationID.y >= u_unis.m_viewportSize.y)
  50. {
  51. return;
  52. }
  53. const Vec2 fragCoord = Vec2(gl_GlobalInvocationID.xy) + 0.5;
  54. const Vec2 uv = fragCoord / u_unis.m_viewportSizef;
  55. #else
  56. const Vec2 fragCoord = gl_FragCoord.xy;
  57. const Vec2 uv = in_uv;
  58. #endif
  59. const Vec2 ndc = UV_TO_NDC(uv);
  60. // Get normal
  61. const Vec3 worldNormal = unpackNormalFromGBuffer(textureLod(u_gbufferRt2, u_linearAnyClampSampler, uv, 0.0));
  62. const Vec3 viewNormal = (u_clusteredShading.m_matrices.m_view * Vec4(worldNormal, 0.0)).xyz;
  63. // Get origin
  64. const F32 depth = textureLod(u_depthRt, u_linearAnyClampSampler, uv, 0.0).r;
  65. Vec4 v4 = u_clusteredShading.m_matrices.m_invertedViewProjectionJitter * Vec4(ndc, depth, 1.0);
  66. const Vec3 worldPos = v4.xyz / v4.w;
  67. v4 = u_clusteredShading.m_matrices.m_invertedProjectionJitter * Vec4(ndc, depth, 1.0);
  68. const Vec3 viewPos = v4.xyz / v4.w;
  69. // SSGI
  70. ANKI_RP Vec3 outColor = Vec3(0.0);
  71. ANKI_RP F32 ssao = 0.0;
  72. if(ENABLE_SSGI)
  73. {
  74. // Find the projected radius
  75. const ANKI_RP Vec3 sphereLimit = viewPos + Vec3(u_unis.m_radius, 0.0, 0.0);
  76. const ANKI_RP Vec4 projSphereLimit = cheapProject(Vec4(sphereLimit, 1.0));
  77. const ANKI_RP Vec2 projSphereLimit2 = projSphereLimit.xy / projSphereLimit.w;
  78. const ANKI_RP F32 projRadius = length(projSphereLimit2 - ndc);
  79. // Loop to compute
  80. #if defined(ANKI_COMPUTE_SHADER)
  81. const UVec2 globalInvocation = gl_GlobalInvocationID.xy;
  82. #else
  83. const UVec2 globalInvocation = UVec2(gl_FragCoord.xy);
  84. #endif
  85. const UVec2 random = rand3DPCG16(UVec3(globalInvocation, u_clusteredShading.m_frame)).xy;
  86. const F32 aspectRatio = u_unis.m_viewportSizef.x / u_unis.m_viewportSizef.y;
  87. for(U32 i = 0u; i < u_unis.m_sampleCount; ++i)
  88. {
  89. const Vec2 point = UV_TO_NDC(hammersleyRandom16(i, u_unis.m_sampleCount, random)) * Vec2(1.0, aspectRatio);
  90. const Vec2 finalDiskPoint = ndc + point * projRadius;
  91. // Do a cheap unproject in view space
  92. const F32 d = textureLod(u_depthRt, u_linearAnyClampSampler, NDC_TO_UV(finalDiskPoint), 0.0).r;
  93. const F32 z = u_clusteredShading.m_matrices.m_unprojectionParameters.z
  94. / (u_clusteredShading.m_matrices.m_unprojectionParameters.w + d);
  95. const Vec2 xy = finalDiskPoint * u_clusteredShading.m_matrices.m_unprojectionParameters.xy * z;
  96. const Vec3 s = Vec3(xy, z);
  97. // Compute factor
  98. const Vec3 dir = s - viewPos;
  99. const F32 len = length(dir);
  100. const Vec3 n = normalize(dir);
  101. const F32 NoL = max(0.0, dot(viewNormal, n));
  102. // const F32 distFactor = 1.0 - sin(min(1.0, len / u_unis.m_radius) * PI / 2.0);
  103. const F32 distFactor = 1.0 - min(1.0, len / u_unis.m_radius);
  104. // Compute the UV for sampling the pyramid
  105. const Vec2 crntFrameUv = NDC_TO_UV(finalDiskPoint);
  106. Vec2 lastFrameUv;
  107. if(REPROJECT_LIGHTBUFFER)
  108. {
  109. lastFrameUv =
  110. crntFrameUv + textureLod(u_motionVectorsTex, u_linearAnyClampSampler, crntFrameUv, 0.0).xy;
  111. }
  112. else
  113. {
  114. lastFrameUv = crntFrameUv;
  115. }
  116. // Append color
  117. const F32 w = distFactor * NoL;
  118. const ANKI_RP Vec3 c = textureLod(u_lightBufferRt, u_linearAnyClampSampler, lastFrameUv, 100.0).xyz;
  119. outColor += c * w;
  120. // Compute SSAO as well
  121. ssao += max(dot(viewNormal, dir) + u_unis.m_ssaoBias, EPSILON) / max(len * len, EPSILON);
  122. }
  123. const ANKI_RP F32 scount = 1.0 / u_unis.m_sampleCountf;
  124. outColor *= scount * 2.0 * PI;
  125. ssao *= scount;
  126. }
  127. ssao = min(1.0, 1.0 - ssao * u_unis.m_ssaoStrength);
  128. if(ENABLE_PROBES)
  129. {
  130. // Sample probes
  131. ANKI_RP Vec3 probeColor = Vec3(0.0);
  132. // Get the cluster
  133. Cluster cluster = getClusterFragCoord(Vec3(fragCoord * 2.0, depth));
  134. if(bitCount(cluster.m_giProbesMask) == 1)
  135. {
  136. // All subgroups point to the same probe and there is only one probe, do a fast path without blend weight
  137. const GlobalIlluminationProbe probe = u_giProbes[findLSB2(cluster.m_giProbesMask)];
  138. // Sample
  139. probeColor = sampleGlobalIllumination(worldPos, worldNormal, probe, u_globalIlluminationTextures,
  140. u_linearAnyClampSampler);
  141. }
  142. else
  143. {
  144. // Zero or more than one probes, do a slow path that blends them together
  145. F32 totalBlendWeight = EPSILON;
  146. // Loop probes
  147. ANKI_LOOP while(cluster.m_giProbesMask != 0u)
  148. {
  149. const U32 idx = U32(findLSB2(cluster.m_giProbesMask));
  150. cluster.m_giProbesMask &= ~(1u << idx);
  151. const GlobalIlluminationProbe probe = u_giProbes[idx];
  152. // Compute blend weight
  153. const F32 blendWeight =
  154. computeProbeBlendWeight(worldPos, probe.m_aabbMin, probe.m_aabbMax, probe.m_fadeDistance);
  155. totalBlendWeight += blendWeight;
  156. // Sample
  157. const ANKI_RP Vec3 c = sampleGlobalIllumination(worldPos, worldNormal, probe,
  158. u_globalIlluminationTextures, u_linearAnyClampSampler);
  159. probeColor += c * blendWeight;
  160. }
  161. // Normalize
  162. probeColor /= totalBlendWeight;
  163. }
  164. outColor = SSGI_PROBE_COMBINE(outColor, probeColor);
  165. }
  166. // Remove fireflies
  167. if(REMOVE_FIREFLIES)
  168. {
  169. const F32 lum = computeLuminance(outColor) + 0.001;
  170. const F32 averageLum = (subgroupAdd(lum) / F32(gl_SubgroupSize)) * 2.0;
  171. const F32 newLum = min(lum, averageLum);
  172. outColor *= newLum / lum;
  173. }
  174. // Apply SSAO
  175. outColor *= ssao;
  176. // Blend color with history
  177. {
  178. const Vec2 historyUv = uv + textureLod(u_motionVectorsTex, u_linearAnyClampSampler, uv, 0.0).xy;
  179. const F32 historyLength = textureLod(u_historyLengthTex, u_linearAnyClampSampler, uv, 0.0).x;
  180. const F32 lowestBlendFactor = 0.05;
  181. const F32 maxHistoryLength = 16.0;
  182. const F32 stableFrames = 4.0;
  183. const F32 lerp = min(1.0, (historyLength * maxHistoryLength - 1.0) / stableFrames);
  184. const F32 blendFactor = mix(1.0, lowestBlendFactor, lerp);
  185. // Blend with history
  186. if(blendFactor < 1.0)
  187. {
  188. const ANKI_RP Vec3 history = textureLod(u_historyTex, u_linearAnyClampSampler, historyUv, 0.0).rgb;
  189. outColor = mix(history, outColor, blendFactor);
  190. }
  191. }
  192. // Store color
  193. #if defined(ANKI_COMPUTE_SHADER)
  194. imageStore(u_outImage, IVec2(gl_GlobalInvocationID.xy), Vec4(outColor, 1.0));
  195. #else
  196. out_color = outColor;
  197. #endif
  198. }