Reflections.ankiprog 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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. layout(ANKI_SS_BINDING(0, 2)) buffer b_
  50. {
  51. vec4 u_irradianceSh[];
  52. };
  53. // Temp buffer to hold the indirect color
  54. shared vec3 s_pixels[WORKGROUP_SIZE.y][WORKGROUP_SIZE.x];
  55. #define u_normalMat mat3(u_viewMat)
  56. vec4 returnSslrColor(vec3 raySample, float factor, float roughness)
  57. {
  58. // Re-project previous frame
  59. vec4 v4 = u_prevViewProjMatMulInvViewProjMat * vec4(UV_TO_NDC(raySample.xy), raySample.z, 1.0);
  60. raySample.xy = NDC_TO_UV(v4.xy / v4.w);
  61. raySample.xy = saturate(raySample.xy);
  62. vec2 ndc = abs(UV_TO_NDC(raySample.xy));
  63. float contribution = max(ndc.x, ndc.y);
  64. contribution = 1.0 - contribution * contribution;
  65. contribution *= factor;
  66. float lod = float(LIGHT_BUFFER_MIP_COUNT - 1u) * roughness;
  67. vec3 color = textureLod(u_lightBufferRt, raySample.xy, lod).rgb;
  68. return vec4(color, contribution);
  69. }
  70. // Note: All calculations in view space
  71. vec4 doSslr(vec3 r, vec3 n, vec3 viewPos, vec2 uv, float depth, float roughness)
  72. {
  73. vec3 p0 = viewPos;
  74. // Check for view facing reflections [sakibsaikia]
  75. vec3 viewDir = normalize(viewPos);
  76. float cameraFacingReflectionAttenuation = 1.0 - smoothstep(0.25, 0.5, dot(-viewDir, r));
  77. if(cameraFacingReflectionAttenuation <= 0.0)
  78. {
  79. return vec4(0.0);
  80. }
  81. // Compute an end point p1. This point is supposed to fall in front of the near plane. Add a small padding to near
  82. // to avoid having p1 touching the near plane.
  83. vec3 p1 = p0 + r * (-p0.z - (u_near + 0.1));
  84. // Start point
  85. vec3 start = vec3(uv, depth);
  86. // Project end point
  87. vec4 end4 = u_projMat * vec4(p1, 1.0);
  88. vec3 end = end4.xyz / end4.w;
  89. end.xy = NDC_TO_UV(end.xy);
  90. // Compute the ray and step size
  91. vec3 ray = end - start;
  92. vec2 texelDims = abs(ray.xy) * vec2(HIZ_SIZE);
  93. float stepSize = length(ray.xy) / max(texelDims.x, texelDims.y);
  94. ray = normalize(ray);
  95. // Compute step
  96. const uint BIG_STEP_SKIP = 32u;
  97. uint stepSkip = BIG_STEP_SKIP;
  98. uint l = gl_GlobalInvocationID.x & 1u;
  99. uint j = gl_GlobalInvocationID.y & 1u;
  100. const uint STEPS_ARR[4] = uint[](6u, 25u, 13u, 18u);
  101. uint step = STEPS_ARR[l * 2u + j];
  102. // Iterate
  103. bool found = false;
  104. vec3 raySample;
  105. ANKI_LOOP for(uint iterations = 0u; iterations < MAX_STEPS; ++iterations)
  106. {
  107. raySample = start + ray * (float(step) * stepSize);
  108. // Check if it's out of the view
  109. if(raySample.x <= 0.0 || raySample.y <= 0.0 || raySample.x >= 1.0 || raySample.y >= 1.0)
  110. {
  111. break;
  112. }
  113. float depth = textureLod(u_hizRt, raySample.xy, 0.0).r;
  114. bool hit = raySample.z - depth >= 0.0;
  115. if(!hit)
  116. {
  117. step += stepSkip;
  118. }
  119. else if(stepSkip > 1)
  120. {
  121. step -= BIG_STEP_SKIP - 1u;
  122. stepSkip = 1u;
  123. }
  124. else
  125. {
  126. found = true;
  127. break;
  128. }
  129. }
  130. //return vec4(heatmap(float(iterations) / float(MAX_STEPS)), 1.0);
  131. if(found)
  132. {
  133. return returnSslrColor(raySample, cameraFacingReflectionAttenuation, roughness);
  134. }
  135. else
  136. {
  137. return vec4(0.0);
  138. }
  139. }
  140. // Note: All calculations in world space
  141. void readReflectionsAndIrradianceFromProbes(
  142. uint idxOffset, vec3 worldPos, vec3 normal, float roughness, out vec3 specIndirect, out vec3 diffIndirect)
  143. {
  144. specIndirect = vec3(0.0);
  145. diffIndirect = vec3(0.0);
  146. vec3 viewDir = normalize(worldPos - u_cameraPos);
  147. vec3 reflDir = reflect(viewDir, normal);
  148. float reflLod = float(IR_MIPMAP_COUNT - 1u) * roughness;
  149. // Check proxy
  150. uint count = u_lightIndices[idxOffset++];
  151. ANKI_LOOP while(count-- != 0)
  152. {
  153. uint probeIdx = u_lightIndices[idxOffset++];
  154. ReflectionProbe probe = u_reflectionProbes[probeIdx];
  155. float R2 = probe.positionRadiusSq.w;
  156. vec3 center = probe.positionRadiusSq.xyz;
  157. // Get distance from the center of the probe
  158. vec3 f = worldPos - center;
  159. // Cubemap UV in view space
  160. vec3 uv = computeCubemapVecAccurate(reflDir, R2, f);
  161. // Read!
  162. float cubemapIndex = probe.cubemapIndexPad3.x;
  163. vec3 c = textureLod(u_reflectionsTex, vec4(uv, cubemapIndex), reflLod).rgb;
  164. // Combine (lerp) with previous color
  165. float d = dot(f, f);
  166. float factor = d / R2;
  167. factor = min(factor, 1.0);
  168. specIndirect = mix(c, specIndirect, factor);
  169. // Do the same for diffuse
  170. if(gl_GlobalInvocationID.x > 2560. / 2. / 2.)
  171. {
  172. uv = computeCubemapVecAccurate(normal, R2, f);
  173. vec3 id = textureLod(u_irradianceTex, vec4(uv, cubemapIndex), 0.0).rgb;
  174. diffIndirect = mix(id, diffIndirect, factor);
  175. }
  176. else
  177. {
  178. vec3 nn = normal.yzx;
  179. vec3 id;
  180. for(uint i = 0u; i < 3u; ++i)
  181. {
  182. vec4 sh = u_irradianceSh[uint(cubemapIndex) * 3u + i];
  183. id[i] = dot(sh, vec4(1.0, nn));
  184. //id[i] = sh[i];
  185. }
  186. diffIndirect = mix(id, diffIndirect, factor);
  187. }
  188. }
  189. }
  190. void main()
  191. {
  192. // Compute a global invocation ID that takes the checkerboard pattern into account
  193. ivec2 fixedInvocationId = ivec2(gl_GlobalInvocationID.xy);
  194. fixedInvocationId.x *= 2;
  195. #if VARIANT == 0
  196. fixedInvocationId.x += ((fixedInvocationId.y + 1) & 1);
  197. #else
  198. fixedInvocationId.x += ((fixedInvocationId.y + 0) & 1);
  199. #endif
  200. if(fixedInvocationId.x >= int(FB_SIZE.x) || fixedInvocationId.y >= int(FB_SIZE.y))
  201. {
  202. // Skip threads outside the writable image
  203. return;
  204. }
  205. vec2 uv = (vec2(fixedInvocationId) + 0.5) / vec2(FB_SIZE);
  206. vec2 ndc = UV_TO_NDC(uv);
  207. // Read gbuffer
  208. GbufferInfo gbuffer;
  209. readGBuffer(u_gbufferRt0, u_gbufferRt1, u_gbufferRt2, uv, 0.0, gbuffer);
  210. // Get depth
  211. float depth = textureLod(u_depthRt, uv, 0.0).r;
  212. // Get world position
  213. vec4 worldPos4 = u_invViewProjMat * vec4(ndc, depth, 1.0);
  214. vec3 worldPos = worldPos4.xyz / worldPos4.w;
  215. // Compute env BRDF
  216. vec3 env;
  217. {
  218. vec3 viewDir = normalize(u_cameraPos - worldPos);
  219. float NoV = max(EPSILON, dot(gbuffer.normal, viewDir));
  220. env = envBRDF(gbuffer.specular, gbuffer.roughness, u_integrationLut, NoV);
  221. }
  222. // Try SSR
  223. float sslrFactor = 0.0;
  224. vec3 sslrCol = vec3(0.0);
  225. if(env.g > 0.05)
  226. {
  227. // Get view pos
  228. vec4 viewPos4 = u_invProjMat * vec4(UV_TO_NDC(uv), depth, 1.0);
  229. vec3 viewPos = viewPos4.xyz / viewPos4.w;
  230. // Do SSLR
  231. vec3 viewDir = normalize(viewPos);
  232. vec3 viewNormal = u_normalMat * gbuffer.normal;
  233. vec3 reflVec = reflect(viewDir, viewNormal);
  234. vec4 sslr = doSslr(reflVec, viewNormal, viewPos, uv, depth, gbuffer.roughness);
  235. sslrFactor = sslr.w;
  236. sslrCol = sslr.xyz;
  237. sslrCol = clamp(sslrCol, 0.0, FLT_MAX); // Fix the value just in case
  238. }
  239. // Read probes
  240. vec3 probeCol = vec3(0.0);
  241. vec3 indirectCol = vec3(0.0);
  242. {
  243. // Get first light index
  244. uint clusterIdx = computeClusterIndex(u_clustererMagic, uv, worldPos, CLUSTER_COUNT_X, CLUSTER_COUNT_Y);
  245. uint idxOffset = u_clusters[clusterIdx];
  246. // Skip decals
  247. uint count = u_lightIndices[idxOffset++];
  248. idxOffset += count;
  249. // Skip point lights
  250. count = u_lightIndices[idxOffset++];
  251. idxOffset += count;
  252. // Skip spot lights
  253. count = u_lightIndices[idxOffset++];
  254. idxOffset += count;
  255. // Do the probe read
  256. readReflectionsAndIrradianceFromProbes(
  257. idxOffset, worldPos, gbuffer.normal, gbuffer.roughness, probeCol, indirectCol);
  258. }
  259. // Combine the SSR and probe reflections and write the result
  260. vec3 finalRefl = mix(probeCol, sslrCol, sslrFactor);
  261. // Compute the final color
  262. vec3 outColor = indirectCol /* gbuffer.diffuse + finalRefl * env*/;
  263. // Store the color for the resolve
  264. s_pixels[gl_LocalInvocationID.y][gl_LocalInvocationID.x] = outColor;
  265. // Wait for all the threads to store their stuff
  266. memoryBarrierShared();
  267. barrier();
  268. // Compute the missing pixel by resolving with the right or left neighbour
  269. ivec2 readPixel, storePixel;
  270. readPixel.y = int(gl_LocalInvocationID.y);
  271. storePixel.y = fixedInvocationId.y;
  272. #if VARIANT == 0
  273. bool pickRightNeighbour = (fixedInvocationId.y & 1) == 1;
  274. #else
  275. bool pickRightNeighbour = (fixedInvocationId.y & 1) == 0;
  276. #endif
  277. int xOffset = (pickRightNeighbour) ? 1 : -1;
  278. readPixel.x = int(gl_LocalInvocationID.x) + xOffset;
  279. readPixel.x = clamp(readPixel.x, 0, int(WORKGROUP_SIZE.x - 1));
  280. storePixel.x = fixedInvocationId.x + xOffset;
  281. vec3 missingColor = (outColor + s_pixels[readPixel.y][readPixel.x]) * 0.5; // average
  282. // Store both the pixels
  283. imageStore(out_reflAndIndirect, fixedInvocationId, vec4(outColor, 0.0));
  284. imageStore(out_reflAndIndirect, storePixel, vec4(missingColor, 0.0));
  285. }
  286. ]]></source>
  287. </shader>
  288. </shaders>
  289. </shaderProgram>