ImageReflections.glsl 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Copyright (C) 2009-2016, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. // Contains resources and functions for image reflections
  6. #ifndef ANKI_SHADERS_IMAGE_REFLECTIONS_GLSL
  7. #define ANKI_SHADERS_IMAGE_REFLECTIONS_GLSL
  8. #include "shaders/Clusterer.glsl"
  9. // Representation of a reflection probe
  10. struct ReflectionProbe
  11. {
  12. // Position of the prove in view space. Radius of probe squared
  13. vec4 positionRadiusSq;
  14. // Slice in u_reflectionsTex vector.
  15. vec4 cubemapIndexPad3;
  16. };
  17. layout(std140,
  18. row_major,
  19. SS_BINDING(IMAGE_REFLECTIONS_SET,
  20. IMAGE_REFLECTIONS_FIRST_SS_BINDING)) readonly buffer _irs1
  21. {
  22. mat3 u_invViewRotation;
  23. vec4 u_nearClusterMagicPad2;
  24. ReflectionProbe u_reflectionProbes[];
  25. };
  26. layout(std430,
  27. row_major,
  28. SS_BINDING(IMAGE_REFLECTIONS_SET,
  29. IMAGE_REFLECTIONS_FIRST_SS_BINDING + 1)) readonly buffer _irs2
  30. {
  31. uint u_reflectionProbeIndices[];
  32. };
  33. layout(std430,
  34. row_major,
  35. SS_BINDING(IMAGE_REFLECTIONS_SET,
  36. IMAGE_REFLECTIONS_FIRST_SS_BINDING + 2)) readonly buffer _irs3
  37. {
  38. uvec2 u_reflectionClusters[];
  39. };
  40. layout(TEX_BINDING(IMAGE_REFLECTIONS_SET,
  41. IMAGE_REFLECTIONS_TEX_BINDING)) uniform samplerCubeArray u_reflectionsTex;
  42. layout(TEX_BINDING(IMAGE_REFLECTIONS_SET,
  43. IMAGE_REFLECTIONS_TEX_BINDING
  44. + 1)) uniform samplerCubeArray u_irradianceTex;
  45. layout(TEX_BINDING(IMAGE_REFLECTIONS_SET,
  46. IMAGE_REFLECTIONS_TEX_BINDING + 2)) uniform sampler2D u_integrationLut;
  47. //==============================================================================
  48. // Compute the cubemap texture lookup vector given the reflection vector (r)
  49. // the radius squared of the probe (R2) and the frag pos in sphere space (f)
  50. vec3 computeCubemapVecAccurate(in vec3 r, in float R2, in vec3 f)
  51. {
  52. // Compute the collision of the r to the inner part of the sphere
  53. // From now on we work on the sphere's space
  54. // Project the center of the sphere (it's zero now since we are in sphere
  55. // space) in ray "f,r"
  56. vec3 p = f - r * dot(f, r);
  57. // The collision to the sphere is point x where x = p + T * r
  58. // Because of the pythagorean theorem: R^2 = dot(p, p) + dot(T * r, T * r)
  59. // solving for T, T = R / |p|
  60. // then x becomes x = sqrt(R^2 - dot(p, p)) * r + p;
  61. float pp = dot(p, p);
  62. pp = min(pp, R2);
  63. float sq = sqrt(R2 - pp);
  64. vec3 x = p + sq * r;
  65. // Rotate UV to move it to world space
  66. vec3 uv = u_invViewRotation * x;
  67. return uv;
  68. }
  69. //==============================================================================
  70. // Cheap version of computeCubemapVecAccurate
  71. vec3 computeCubemapVecCheap(in vec3 r, in float R2, in vec3 f)
  72. {
  73. return u_invViewRotation * r;
  74. }
  75. //==============================================================================
  76. void readIndirectInternal(in uint clusterIndex,
  77. in vec3 posVSpace,
  78. in vec3 r,
  79. in vec3 n,
  80. in float lod,
  81. out vec3 specIndirect,
  82. out vec3 diffIndirect)
  83. {
  84. specIndirect = vec3(0.0);
  85. diffIndirect = vec3(0.0);
  86. // Check proxy
  87. uvec2 cluster = u_reflectionClusters[clusterIndex];
  88. uint indexOffset = cluster[0];
  89. uint indexCount = cluster[1];
  90. for(uint i = 0; i < indexCount; ++i)
  91. {
  92. uint probeIndex = u_reflectionProbeIndices[indexOffset++];
  93. ReflectionProbe probe = u_reflectionProbes[probeIndex];
  94. float R2 = probe.positionRadiusSq.w;
  95. vec3 center = probe.positionRadiusSq.xyz;
  96. // Get distance from the center of the probe
  97. vec3 f = posVSpace - center;
  98. // Cubemap UV in view space
  99. vec3 uv = computeCubemapVecAccurate(r, R2, f);
  100. // Read!
  101. float cubemapIndex = probe.cubemapIndexPad3.x;
  102. vec3 c = textureLod(u_reflectionsTex, vec4(uv, cubemapIndex), lod).rgb;
  103. // Combine (lerp) with previous color
  104. float d = dot(f, f);
  105. float factor = d / R2;
  106. factor = min(factor, 1.0);
  107. specIndirect = mix(c, specIndirect, factor);
  108. // Same as: specIndirect = c * (1.0 - factor) + specIndirect * factor
  109. // Do the same for diffuse
  110. uv = computeCubemapVecCheap(n, R2, f);
  111. vec3 id = texture(u_irradianceTex, vec4(uv, cubemapIndex)).rgb;
  112. diffIndirect = mix(id, diffIndirect, factor);
  113. }
  114. }
  115. //==============================================================================
  116. void readIndirect(in vec3 posVSpace,
  117. in vec3 r,
  118. in vec3 n,
  119. in float lod,
  120. out vec3 specIndirect,
  121. out vec3 diffIndirect)
  122. {
  123. uint clusterIdx =
  124. computeClusterIndexUsingFragCoord(u_nearClusterMagicPad2.x,
  125. u_nearClusterMagicPad2.y,
  126. posVSpace.z,
  127. TILE_COUNT_X,
  128. TILE_COUNT_Y);
  129. readIndirectInternal(
  130. clusterIdx, posVSpace, r, n, lod, specIndirect, diffIndirect);
  131. }
  132. #endif