Reflections.ankiprog 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. <!--
  2. Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
  3. All rights reserved.
  4. Code licensed under the BSD License.
  5. http://www.anki3d.org/LICENSE
  6. -->
  7. <shaderProgram>
  8. <mutators>
  9. <mutator name="VARIANT" values="0 1"/>
  10. </mutators>
  11. <shaders>
  12. <shader type="comp">
  13. <inputs>
  14. <input name="FB_SIZE" type="uvec2" const="1"/>
  15. <input name="WORKGROUP_SIZE" type="uvec2" const="1"/>
  16. <input name="MAX_STEPS" type="uint" const="1"/>
  17. <input name="LIGHT_BUFFER_MIP_COUNT" type="uint" const="1"/>
  18. <input name="HIZ_MIP_COUNT" type="uint" const="1"/>
  19. <input name="CLUSTER_COUNT_X" type="uint" const="1"/>
  20. <input name="CLUSTER_COUNT_Y" type="uint" const="1"/>
  21. <input name="CLUSTER_COUNT_Z" type="uint" const="1"/>
  22. <input name="IR_MIPMAP_COUNT" type="uint" const="1"/>
  23. </inputs>
  24. <source><![CDATA[
  25. // if VARIANT==0 then the checkerboard pattern is (render on 'v'):
  26. // -----
  27. // |v| |
  28. // | |v|
  29. // -----
  30. #include "shaders/Functions.glsl"
  31. #include "shaders/Pack.glsl"
  32. #include "shaders/Clusterer.glsl"
  33. #define LIGHT_SET 0
  34. #define LIGHT_SS_BINDING 0
  35. #define LIGHT_UBO_BINDING 0
  36. #define LIGHT_TEX_BINDING 6
  37. #define LIGHT_INDIRECT
  38. #define LIGHT_COMMON_UNIS
  39. #include "shaders/ClusterLightCommon.glsl"
  40. const ivec2 HIZ_SIZE = ivec2(FB_SIZE) >> 1;
  41. layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
  42. layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_gbufferRt0;
  43. layout(ANKI_TEX_BINDING(0, 1)) uniform sampler2D u_gbufferRt1;
  44. layout(ANKI_TEX_BINDING(0, 2)) uniform sampler2D u_gbufferRt2;
  45. layout(ANKI_TEX_BINDING(0, 3)) uniform sampler2D u_depthRt;
  46. layout(ANKI_TEX_BINDING(0, 4)) uniform sampler2D u_hizRt;
  47. layout(ANKI_TEX_BINDING(0, 5)) uniform sampler2D u_lightBufferRt;
  48. layout(ANKI_IMAGE_BINDING(0, 0)) writeonly uniform image2D out_reflAndIndirect;
  49. // Temp buffer to hold the indirect color
  50. shared vec3 s_pixels[WORKGROUP_SIZE.y][WORKGROUP_SIZE.x];
  51. #define u_normalMat mat3(u_viewMat)
  52. vec4 returnSslrColor(vec3 raySample, float factor, float roughness)
  53. {
  54. // Re-project previous frame
  55. vec4 v4 = u_prevViewProjMatMulInvViewProjMat * vec4(UV_TO_NDC(raySample.xy), raySample.z, 1.0);
  56. raySample.xy = NDC_TO_UV(v4.xy / v4.w);
  57. raySample.xy = saturate(raySample.xy);
  58. vec2 ndc = abs(UV_TO_NDC(raySample.xy));
  59. float contribution = max(ndc.x, ndc.y);
  60. contribution = 1.0 - contribution * contribution;
  61. contribution *= factor;
  62. float lod = float(LIGHT_BUFFER_MIP_COUNT - 1u) * roughness;
  63. vec3 color = textureLod(u_lightBufferRt, raySample.xy, lod).rgb;
  64. return vec4(color, contribution);
  65. }
  66. // Note: All calculations in view space
  67. vec4 doSslr(vec3 r, vec3 n, vec3 viewPos, vec2 uv, float depth, float roughness)
  68. {
  69. vec3 p0 = viewPos;
  70. // Check for view facing reflections [sakibsaikia]
  71. vec3 viewDir = normalize(viewPos);
  72. float cameraFacingReflectionAttenuation = 1.0 - smoothstep(0.25, 0.5, dot(-viewDir, r));
  73. if(cameraFacingReflectionAttenuation <= 0.0)
  74. {
  75. return vec4(0.0);
  76. }
  77. // Compute an end point p1. This point is supposed to fall in front of the near plane. Add a small padding to near
  78. // to avoid having p1 touching the near plane.
  79. vec3 p1 = p0 + r * (-p0.z - (u_near + 0.1));
  80. // Start point
  81. vec3 start = vec3(uv, depth);
  82. // Project end point
  83. vec4 end4 = u_projMat * vec4(p1, 1.0);
  84. vec3 end = end4.xyz / end4.w;
  85. end.xy = NDC_TO_UV(end.xy);
  86. // Compute the ray and step size
  87. vec3 ray = end - start;
  88. vec2 texelDims = abs(ray.xy) * vec2(HIZ_SIZE);
  89. float stepSize = length(ray.xy) / max(texelDims.x, texelDims.y);
  90. ray = normalize(ray);
  91. // Compute step
  92. const uint BIG_STEP_SKIP = 32u;
  93. uint stepSkip = BIG_STEP_SKIP;
  94. uint l = gl_GlobalInvocationID.x & 1u;
  95. uint j = gl_GlobalInvocationID.y & 1u;
  96. const uint STEPS_ARR[4] = uint[](6u, 25u, 13u, 18u);
  97. uint step = STEPS_ARR[l * 2u + j];
  98. // Iterate
  99. bool found = false;
  100. vec3 raySample;
  101. uint iterations = 0u;
  102. for(; iterations < MAX_STEPS; ++iterations)
  103. {
  104. raySample = start + ray * (float(step) * stepSize);
  105. // Check if it's out of the view
  106. if(raySample.x <= 0.0 || raySample.y <= 0.0 || raySample.x >= 1.0 || raySample.y >= 1.0)
  107. {
  108. break;
  109. }
  110. float depth = textureLod(u_hizRt, raySample.xy, 0.0).r;
  111. bool hit = raySample.z - depth >= 0.0;
  112. if(!hit)
  113. {
  114. step += stepSkip;
  115. }
  116. else if(stepSkip > 1)
  117. {
  118. step -= BIG_STEP_SKIP - 1u;
  119. stepSkip = 1u;
  120. }
  121. else
  122. {
  123. found = true;
  124. break;
  125. }
  126. }
  127. //return vec4(heatmap(float(iterations) / float(MAX_STEPS)), 1.0);
  128. if(found)
  129. {
  130. return returnSslrColor(raySample, cameraFacingReflectionAttenuation, roughness);
  131. }
  132. else
  133. {
  134. return vec4(0.0);
  135. }
  136. }
  137. // Note: All calculations in world space
  138. void readReflectionsAndIrradianceFromProbes(
  139. uint idxOffset, vec3 worldPos, vec3 normal, float roughness, out vec3 specIndirect, out vec3 diffIndirect)
  140. {
  141. specIndirect = vec3(0.0);
  142. diffIndirect = vec3(0.0);
  143. vec3 viewDir = normalize(worldPos - u_cameraPos);
  144. vec3 reflDir = reflect(viewDir, normal);
  145. float reflLod = float(IR_MIPMAP_COUNT - 1u) * roughness;
  146. // Check proxy
  147. uint count = u_lightIndices[idxOffset++];
  148. while(count-- != 0)
  149. {
  150. ReflectionProbe probe = u_reflectionProbes[u_lightIndices[idxOffset++]];
  151. float R2 = probe.positionRadiusSq.w;
  152. vec3 center = probe.positionRadiusSq.xyz;
  153. // Get distance from the center of the probe
  154. vec3 f = worldPos - center;
  155. // Cubemap UV in view space
  156. vec3 uv = computeCubemapVecAccurate(reflDir, R2, f);
  157. // Read!
  158. float cubemapIndex = probe.cubemapIndexPad3.x;
  159. vec3 c = textureLod(u_reflectionsTex, vec4(uv, cubemapIndex), reflLod).rgb;
  160. // Combine (lerp) with previous color
  161. float d = dot(f, f);
  162. float factor = d / R2;
  163. factor = min(factor, 1.0);
  164. specIndirect = mix(c, specIndirect, factor);
  165. // Do the same for diffuse
  166. uv = computeCubemapVecAccurate(normal, R2, f);
  167. vec3 id = textureLod(u_irradianceTex, vec4(uv, cubemapIndex), 0.0).rgb;
  168. diffIndirect = mix(id, diffIndirect, factor);
  169. }
  170. }
  171. vec3 computeSpecIndirectFactor(vec3 worldPos, vec3 normal, float roughness, vec3 specColor)
  172. {
  173. vec3 viewDir = normalize(u_cameraPos - worldPos);
  174. float ndotv = dot(normal, viewDir);
  175. vec2 envBRDF = texture(u_integrationLut, vec2(roughness, ndotv)).xy;
  176. vec3 specIndirectTerm = specColor * envBRDF.x + envBRDF.y;
  177. return specIndirectTerm;
  178. }
  179. void main()
  180. {
  181. // Compute a global invocation ID that takes the checkerboard pattern into account
  182. ivec2 fixedInvocationId = ivec2(gl_GlobalInvocationID.xy);
  183. fixedInvocationId.x *= 2;
  184. #if VARIANT == 0
  185. fixedInvocationId.x += ((fixedInvocationId.y + 1) & 1);
  186. #else
  187. fixedInvocationId.x += ((fixedInvocationId.y + 0) & 1);
  188. #endif
  189. if(fixedInvocationId.x >= int(FB_SIZE.x) || fixedInvocationId.y >= int(FB_SIZE.y))
  190. {
  191. // Skip threads outside the writable image
  192. return;
  193. }
  194. vec2 uv = (vec2(fixedInvocationId) + 0.5) / vec2(FB_SIZE);
  195. vec2 ndc = UV_TO_NDC(uv);
  196. // Read gbuffer
  197. GbufferInfo gbuffer;
  198. readGBuffer(u_gbufferRt0, u_gbufferRt1, u_gbufferRt2, uv, 0.0, gbuffer);
  199. // Get depth
  200. float depth = textureLod(u_depthRt, uv, 0.0).r;
  201. // Get world position
  202. vec4 worldPos4 = u_invViewProjMat * vec4(ndc, depth, 1.0);
  203. vec3 worldPos = worldPos4.xyz / worldPos4.w;
  204. // Compute how much reflections we need
  205. float a2 = computeRoughnesSquared(gbuffer.roughness);
  206. vec3 specIndirectTerm = computeSpecIndirectFactor(worldPos, gbuffer.normal, a2, gbuffer.specular);
  207. bool runSslr =
  208. max(max(specIndirectTerm.x, specIndirectTerm.y), specIndirectTerm.z) > 0.05;
  209. // Try SSR
  210. float sslrFactor = 0.0;
  211. vec3 sslrCol = vec3(0.0);
  212. if(runSslr)
  213. {
  214. // Get view pos
  215. vec4 viewPos4 = u_invProjMat * vec4(UV_TO_NDC(uv), depth, 1.0);
  216. vec3 viewPos = viewPos4.xyz / viewPos4.w;
  217. // Do SSLR
  218. vec3 viewDir = normalize(viewPos);
  219. vec3 viewNormal = u_normalMat * gbuffer.normal;
  220. vec3 reflVec = reflect(viewDir, viewNormal);
  221. vec4 sslr = doSslr(reflVec, viewNormal, viewPos, uv, depth, gbuffer.roughness);
  222. sslrFactor = sslr.w;
  223. sslrCol = sslr.xyz;
  224. sslrCol = clamp(sslrCol, 0.0, FLT_MAX); // Fix the value just in case
  225. }
  226. // Read probes
  227. vec3 probeCol = vec3(0.0);
  228. vec3 indirectCol = vec3(0.0);
  229. {
  230. // Get first light index
  231. uint clusterIdx = computeClusterIndex(u_clustererMagic, uv, worldPos, CLUSTER_COUNT_X, CLUSTER_COUNT_Y);
  232. uint idxOffset = u_clusters[clusterIdx];
  233. // Skip decals
  234. uint count = u_lightIndices[idxOffset++];
  235. idxOffset += count;
  236. // Skip point lights
  237. count = u_lightIndices[idxOffset++];
  238. idxOffset += count;
  239. // Skip spot lights
  240. count = u_lightIndices[idxOffset++];
  241. idxOffset += count;
  242. // Do the probe read
  243. readReflectionsAndIrradianceFromProbes(
  244. idxOffset, worldPos, gbuffer.normal, gbuffer.roughness, probeCol, indirectCol);
  245. }
  246. vec3 outColor = indirectCol * gbuffer.diffuse;
  247. // Combine the SSR and probe reflections and write the result
  248. {
  249. vec3 finalRefl = mix(probeCol, sslrCol, sslrFactor);
  250. finalRefl = specIndirectTerm * finalRefl;
  251. outColor += finalRefl;
  252. }
  253. // Store the color for the resolve
  254. s_pixels[gl_LocalInvocationID.y][gl_LocalInvocationID.x] = outColor;
  255. // Wait for all the threads to store their stuff
  256. memoryBarrierShared();
  257. barrier();
  258. // Compute the missing pixel by resolving with the right or left neighbour
  259. ivec2 readPixel, storePixel;
  260. readPixel.y = int(gl_LocalInvocationID.y);
  261. storePixel.y = fixedInvocationId.y;
  262. #if VARIANT == 0
  263. bool pickRightNeighbour = (fixedInvocationId.y & 1) == 1;
  264. #else
  265. bool pickRightNeighbour = (fixedInvocationId.y & 1) == 0;
  266. #endif
  267. int xOffset = (pickRightNeighbour) ? 1 : -1;
  268. readPixel.x = int(gl_LocalInvocationID.x) + xOffset;
  269. readPixel.x = clamp(readPixel.x, 0, int(WORKGROUP_SIZE.x - 1));
  270. storePixel.x = fixedInvocationId.x + xOffset;
  271. vec3 missingColor = (outColor + s_pixels[readPixel.y][readPixel.x]) * 0.5; // average
  272. // Store both the pixels
  273. imageStore(out_reflAndIndirect, fixedInvocationId, vec4(outColor, 0.0));
  274. imageStore(out_reflAndIndirect, storePixel, vec4(missingColor, 0.0));
  275. }
  276. ]]></source>
  277. </shader>
  278. </shaders>
  279. </shaderProgram>