2
0

LightShading.ankiprog 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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. ANKI_SPECIALIZATION_CONSTANT_U32(CLUSTER_COUNT_X, 0, 1u);
  6. ANKI_SPECIALIZATION_CONSTANT_U32(CLUSTER_COUNT_Y, 1, 1u);
  7. ANKI_SPECIALIZATION_CONSTANT_U32(CLUSTER_COUNT_Z, 2, 1u);
  8. ANKI_SPECIALIZATION_CONSTANT_U32(CLUSTER_COUNT, 3, 1u);
  9. ANKI_SPECIALIZATION_CONSTANT_U32(IR_MIPMAP_COUNT, 4, 1u);
  10. #pragma anki start vert
  11. #include <shaders/Common.glsl>
  12. layout(location = 0) out Vec2 out_uv;
  13. layout(location = 1) out Vec2 out_clusterIJ;
  14. out gl_PerVertex
  15. {
  16. Vec4 gl_Position;
  17. };
  18. void main()
  19. {
  20. out_uv = Vec2(gl_VertexID & 1, gl_VertexID >> 1) * 2.0;
  21. Vec2 pos = out_uv * 2.0 - 1.0;
  22. gl_Position = Vec4(pos, 0.0, 1.0);
  23. out_clusterIJ = Vec2(CLUSTER_COUNT_X, CLUSTER_COUNT_Y) * out_uv;
  24. }
  25. #pragma anki end
  26. #pragma anki start frag
  27. #include <shaders/Pack.glsl>
  28. #include <shaders/Functions.glsl>
  29. #define LIGHT_SET 0
  30. #define LIGHT_COMMON_UNIS_BINDING 0
  31. #define LIGHT_LIGHTS_BINDING 1
  32. #define LIGHT_INDIRECT_SPECULAR_BINDING 4
  33. #define LIGHT_GLOBAL_ILLUMINATION_BINDING 7
  34. #define LIGHT_CLUSTERS_BINDING 9
  35. #include <shaders/ClusteredShadingCommon.glsl>
  36. layout(set = 0, binding = 11) uniform sampler u_nearestAnyClampSampler;
  37. layout(set = 0, binding = 12) uniform sampler u_trilinearClampSampler;
  38. layout(set = 0, binding = 13) uniform texture2D u_msRt0;
  39. layout(set = 0, binding = 14) uniform texture2D u_msRt1;
  40. layout(set = 0, binding = 15) uniform texture2D u_msRt2;
  41. layout(set = 0, binding = 16) uniform texture2D u_msDepthRt;
  42. layout(set = 0, binding = 17) uniform texture2D u_ssrRt;
  43. layout(set = 0, binding = 18) uniform texture2D u_ssaoRt;
  44. layout(set = 0, binding = 19) uniform texture2D u_ssgiRt;
  45. layout(set = 0, binding = 20) uniform texture2D u_resolvedSm;
  46. layout(location = 0) in Vec2 in_uv;
  47. layout(location = 1) in Vec2 in_clusterIJ;
  48. layout(location = 0) out Vec3 out_color;
  49. // Common code for lighting
  50. #define LIGHTING_COMMON_BRDF() \
  51. const Vec3 frag2Light = light.m_position - worldPos; \
  52. const Vec3 l = normalize(frag2Light); \
  53. const Vec3 specC = computeSpecularColorBrdf(gbuffer, viewDir, l); \
  54. const Vec3 diffC = diffuseLambert(gbuffer.m_diffuse); \
  55. const F32 att = computeAttenuationFactor(light.m_squareRadiusOverOne, frag2Light); \
  56. F32 lambert = max(0.0, dot(gbuffer.m_normal, l));
  57. void main()
  58. {
  59. const F32 depth = textureLod(u_msDepthRt, u_nearestAnyClampSampler, in_uv, 0.0).r;
  60. const Vec2 ndc = UV_TO_NDC(in_uv);
  61. if(depth == 1.0)
  62. {
  63. out_color = Vec3(0.0);
  64. return;
  65. }
  66. // Get world position
  67. const Vec4 worldPos4 = u_invViewProjMat * Vec4(ndc, depth, 1.0);
  68. const Vec3 worldPos = worldPos4.xyz / worldPos4.w;
  69. // Get first light index
  70. U32 idxOffset;
  71. {
  72. U32 k = computeClusterK(u_clustererMagic, worldPos);
  73. U32 clusterIdx =
  74. k * (CLUSTER_COUNT_X * CLUSTER_COUNT_Y) + U32(in_clusterIJ.y) * CLUSTER_COUNT_X + U32(in_clusterIJ.x);
  75. idxOffset = u_clusters[clusterIdx];
  76. // out_color = lightHeatmap(idxOffset, 5, 1u << 3); return;
  77. }
  78. // Decode GBuffer
  79. GbufferInfo gbuffer;
  80. readGBuffer(u_msRt0, u_msRt1, u_msRt2, u_nearestAnyClampSampler, in_uv, 0.0, gbuffer);
  81. gbuffer.m_subsurface = max(gbuffer.m_subsurface, SUBSURFACE_MIN);
  82. // SM
  83. Vec4 resolvedSm = textureLod(u_resolvedSm, u_trilinearClampSampler, in_uv, 0.0);
  84. U32 resolvedSmIdx = 0;
  85. // SSAO
  86. const F32 ssao = textureLod(u_ssaoRt, u_trilinearClampSampler, in_uv, 0.0).r;
  87. gbuffer.m_diffuse *= ssao;
  88. // Ambient and emissive color
  89. out_color = gbuffer.m_diffuse * gbuffer.m_emission;
  90. // Dir light
  91. Vec3 viewDir = normalize(u_cameraPos - worldPos);
  92. if(u_dirLight.m_active != 0u)
  93. {
  94. F32 shadowFactor;
  95. if(u_dirLight.m_cascadeCount > 0)
  96. {
  97. shadowFactor = resolvedSm[0];
  98. ++resolvedSmIdx;
  99. }
  100. else
  101. {
  102. shadowFactor = 1.0;
  103. }
  104. const Vec3 l = -u_dirLight.m_dir;
  105. const F32 lambert = max(gbuffer.m_subsurface, dot(l, gbuffer.m_normal));
  106. const Vec3 diffC = diffuseLambert(gbuffer.m_diffuse);
  107. const Vec3 specC = computeSpecularColorBrdf(gbuffer, viewDir, l);
  108. out_color += (diffC + specC) * u_dirLight.m_diffuseColor * (shadowFactor * lambert);
  109. }
  110. // Point lights
  111. U32 idx;
  112. ANKI_LOOP while((idx = u_lightIndices[idxOffset++]) != MAX_U32)
  113. {
  114. PointLight light = u_pointLights[idx];
  115. LIGHTING_COMMON_BRDF();
  116. ANKI_BRANCH if(light.m_shadowAtlasTileScale >= 0.0)
  117. {
  118. const F32 shadow = resolvedSm[resolvedSmIdx++];
  119. lambert *= shadow;
  120. }
  121. out_color += (diffC + specC) * light.m_diffuseColor * (att * max(gbuffer.m_subsurface, lambert));
  122. }
  123. // Spot lights
  124. ANKI_LOOP while((idx = u_lightIndices[idxOffset++]) != MAX_U32)
  125. {
  126. SpotLight light = u_spotLights[idx];
  127. LIGHTING_COMMON_BRDF();
  128. const F32 spot = computeSpotFactor(l, light.m_outerCos, light.m_innerCos, light.m_dir);
  129. const F32 shadowmapLayerIdx = light.m_shadowmapId;
  130. ANKI_BRANCH if(shadowmapLayerIdx >= 0.0)
  131. {
  132. const F32 shadow = resolvedSm[resolvedSmIdx++];
  133. lambert *= shadow;
  134. }
  135. out_color += (diffC + specC) * light.m_diffuseColor * (att * spot * max(gbuffer.m_subsurface, lambert));
  136. }
  137. // Indirect specular
  138. {
  139. // Do the probe read
  140. Vec3 specIndirect = Vec3(0.0);
  141. const Vec3 reflDir = reflect(-viewDir, gbuffer.m_normal);
  142. const F32 reflLod = F32(IR_MIPMAP_COUNT - 1u) * gbuffer.m_roughness;
  143. if(subgroupAll(u_lightIndices[idxOffset] != MAX_U32 && u_lightIndices[idxOffset + 1u] == MAX_U32))
  144. {
  145. // Only one probe, do a fast path without blend weight
  146. const ReflectionProbe probe = u_reflectionProbes[u_lightIndices[idxOffset]];
  147. idxOffset += 2u;
  148. // Sample
  149. const Vec3 cubeUv = intersectProbe(worldPos, reflDir, probe.m_aabbMin, probe.m_aabbMax, probe.m_position);
  150. const Vec4 cubeArrUv = Vec4(cubeUv, probe.m_cubemapIndex);
  151. specIndirect = textureLod(u_reflectionsTex, u_trilinearClampSampler, cubeArrUv, reflLod).rgb;
  152. }
  153. else
  154. {
  155. // Zero or more than one probes, do a slow path that blends them together
  156. F32 totalBlendWeight = EPSILON;
  157. // Loop probes
  158. ANKI_LOOP while((idx = u_lightIndices[idxOffset++]) != MAX_U32)
  159. {
  160. const ReflectionProbe probe = u_reflectionProbes[idx];
  161. // Compute blend weight
  162. const F32 blendWeight = computeProbeBlendWeight(worldPos, probe.m_aabbMin, probe.m_aabbMax, 0.2);
  163. totalBlendWeight += blendWeight;
  164. // Sample reflections
  165. const Vec3 cubeUv =
  166. intersectProbe(worldPos, reflDir, probe.m_aabbMin, probe.m_aabbMax, probe.m_position);
  167. const Vec4 cubeArrUv = Vec4(cubeUv, probe.m_cubemapIndex);
  168. Vec3 c = textureLod(u_reflectionsTex, u_trilinearClampSampler, cubeArrUv, reflLod).rgb;
  169. specIndirect += c * blendWeight;
  170. }
  171. // Normalize the colors
  172. specIndirect /= totalBlendWeight;
  173. }
  174. // Read the SSL result
  175. const Vec4 ssr = textureLod(u_ssrRt, u_trilinearClampSampler, in_uv, 0.0);
  176. // Combine the SSR and probe reflections and write the result
  177. const Vec3 finalSpecIndirect = specIndirect * ssr.a + ssr.rgb;
  178. // Compute env BRDF
  179. const F32 NoV = max(EPSILON, dot(gbuffer.m_normal, viewDir));
  180. const Vec3 env =
  181. envBRDF(gbuffer.m_specular, gbuffer.m_roughness, u_integrationLut, u_trilinearClampSampler, NoV);
  182. out_color += finalSpecIndirect * env;
  183. }
  184. // Indirect diffuse
  185. {
  186. Vec3 diffIndirect;
  187. const U32 crntProbeIdx = u_lightIndices[idxOffset];
  188. if(subgroupAllEqual(crntProbeIdx)
  189. && subgroupAll(crntProbeIdx != MAX_U32 && u_lightIndices[idxOffset + 1u] == MAX_U32))
  190. {
  191. // All subgroups point to the same probe and there is only one probe, do a fast path without blend weight
  192. GlobalIlluminationProbe probe = u_giProbes[subgroupBroadcastFirst(crntProbeIdx)]; // It should be uniform
  193. // Sample
  194. diffIndirect = sampleGlobalIllumination(worldPos, gbuffer.m_normal, probe, u_globalIlluminationTextures,
  195. u_trilinearClampSampler);
  196. }
  197. else
  198. {
  199. // Zero or more than one probes, do a slow path that blends them together
  200. F32 totalBlendWeight = EPSILON;
  201. diffIndirect = Vec3(0.0);
  202. Bool laneActive = true;
  203. ANKI_LOOP while(laneActive)
  204. {
  205. U32 uniformIdxOffset = subgroupBroadcastFirst(idxOffset); // Should be uniform
  206. const Bool laneMatch = uniformIdxOffset == idxOffset;
  207. if(laneMatch)
  208. {
  209. laneActive = false;
  210. // Loop probes
  211. ANKI_LOOP while((idx = u_lightIndices[uniformIdxOffset++]) != MAX_U32)
  212. {
  213. GlobalIlluminationProbe probe = u_giProbes[idx];
  214. // Compute blend weight
  215. const F32 blendWeight =
  216. computeProbeBlendWeight(worldPos, probe.m_aabbMin, probe.m_aabbMax, probe.m_fadeDistance);
  217. totalBlendWeight += blendWeight;
  218. // Sample
  219. const Vec3 c = sampleGlobalIllumination(worldPos, gbuffer.m_normal, probe,
  220. u_globalIlluminationTextures, u_trilinearClampSampler);
  221. diffIndirect += c * blendWeight;
  222. }
  223. }
  224. }
  225. // Normalize
  226. diffIndirect /= totalBlendWeight;
  227. }
  228. const Vec3 ssgi = textureLod(u_ssgiRt, u_trilinearClampSampler, in_uv, 0.0).rgb;
  229. diffIndirect += ssgi;
  230. out_color += diffIndirect * gbuffer.m_diffuse;
  231. }
  232. }
  233. #pragma anki end