LightFunctions.glsl 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. // Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. // Contains functions for light calculations
  6. #ifndef ANKI_SHADERS_LIGHT_FUNCTIONS_GLSL
  7. #define ANKI_SHADERS_LIGHT_FUNCTIONS_GLSL
  8. #include "shaders/Functions.glsl"
  9. #include "shaders/Pack.glsl"
  10. const float LIGHT_FRUSTUM_NEAR_PLANE = 0.1 / 4.0;
  11. const uint SHADOW_SAMPLE_COUNT = 16;
  12. const float ESM_CONSTANT = 40.0;
  13. // Fresnel term unreal
  14. vec3 F_Unreal(vec3 specular, float VoH)
  15. {
  16. return specular + (1.0 - specular) * pow(2.0, (-5.55473 * VoH - 6.98316) * VoH);
  17. }
  18. // Fresnel Schlick: "An Inexpensive BRDF Model for Physically-Based Rendering"
  19. // It has lower VGRPs than F_Unreal
  20. vec3 F_Schlick(vec3 specular, float VoH)
  21. {
  22. float a = 1.0 - VoH;
  23. float a2 = a * a;
  24. float a5 = a2 * a2 * a; // a5 = a^5
  25. return /*saturate(50.0 * specular.g) */ a5 + (1.0 - a5) * specular;
  26. }
  27. // D(n,h) aka NDF: GGX Trowbridge-Reitz
  28. float D_GGX(float roughness, float NoH)
  29. {
  30. float a = roughness * roughness;
  31. float a2 = a * a;
  32. float D = (NoH * a2 - NoH) * NoH + 1.0;
  33. return a2 / (PI * D * D);
  34. }
  35. // Visibility term: Geometric shadowing divided by BRDF denominator
  36. float V_Schlick(float roughness, float NoV, float NoL)
  37. {
  38. float k = (roughness * roughness) * 0.5;
  39. float Vis_SchlickV = NoV * (1.0 - k) + k;
  40. float Vis_SchlickL = NoL * (1.0 - k) + k;
  41. return 0.25 / (Vis_SchlickV * Vis_SchlickL);
  42. }
  43. vec3 envBRDF(vec3 specular, float roughness, sampler2D integrationLut, float NoV)
  44. {
  45. float a = roughness * roughness;
  46. float a2 = a * a;
  47. vec2 envBRDF = textureLod(integrationLut, vec2(a2, NoV), 0.0).xy;
  48. return specular * envBRDF.x + /*min(1.0, 50.0 * specular.g) */ envBRDF.y;
  49. }
  50. vec3 diffuseLambert(vec3 diffuse)
  51. {
  52. return diffuse * (1.0 / PI);
  53. }
  54. // Performs BRDF specular lighting
  55. vec3 computeSpecularColorBrdf(GbufferInfo gbuffer, vec3 viewDir, vec3 frag2Light)
  56. {
  57. vec3 H = normalize(frag2Light + viewDir);
  58. float NoL = max(EPSILON, dot(gbuffer.normal, frag2Light));
  59. float VoH = max(EPSILON, dot(viewDir, H));
  60. float NoH = max(EPSILON, dot(gbuffer.normal, H));
  61. float NoV = max(EPSILON, dot(gbuffer.normal, viewDir));
  62. // F
  63. #if 0
  64. vec3 F = F_Unreal(gbuffer.specular, VoH);
  65. #else
  66. vec3 F = F_Schlick(gbuffer.specular, VoH);
  67. #endif
  68. // D
  69. float D = D_GGX(gbuffer.roughness, NoH);
  70. // Vis
  71. float V = V_Schlick(gbuffer.roughness, NoV, NoL);
  72. return F * (V * D);
  73. }
  74. float computeSpotFactor(vec3 l, float outerCos, float innerCos, vec3 spotDir)
  75. {
  76. float costheta = -dot(l, spotDir);
  77. float spotFactor = smoothstep(outerCos, innerCos, costheta);
  78. return spotFactor;
  79. }
  80. uint computeShadowSampleCount(const uint COUNT, float zVSpace)
  81. {
  82. const float MAX_DISTANCE = 5.0;
  83. float z = max(zVSpace, -MAX_DISTANCE);
  84. float sampleCountf = float(COUNT) + z * (float(COUNT) / MAX_DISTANCE);
  85. sampleCountf = max(sampleCountf, 1.0);
  86. uint sampleCount = uint(sampleCountf);
  87. return sampleCount;
  88. }
  89. float computeShadowFactorSpot(mat4 lightProjectionMat, vec3 worldPos, float distance, sampler2D spotMapArr)
  90. {
  91. vec4 texCoords4 = lightProjectionMat * vec4(worldPos, 1.0);
  92. vec3 texCoords3 = texCoords4.xyz / texCoords4.w;
  93. const float near = LIGHT_FRUSTUM_NEAR_PLANE;
  94. const float far = distance;
  95. float linearDepth = linearizeDepth(texCoords3.z, near, far);
  96. float shadowFactor = textureLod(spotMapArr, texCoords3.xy, 0.0).r;
  97. return saturate(exp(ESM_CONSTANT * (shadowFactor - linearDepth)));
  98. }
  99. float computeShadowFactorOmni(vec3 frag2Light, float radius, uvec2 atlasTiles, float tileSize, sampler2D shadowMap)
  100. {
  101. vec3 dir = -frag2Light;
  102. vec3 dirabs = abs(dir);
  103. float dist = max(dirabs.x, max(dirabs.y, dirabs.z));
  104. const float near = LIGHT_FRUSTUM_NEAR_PLANE;
  105. const float far = radius;
  106. float linearDepth = (dist - near) / (far - near);
  107. // Read tex
  108. float shadowFactor;
  109. {
  110. // Convert cube coords
  111. uint faceIdxu;
  112. vec2 uv = convertCubeUvsu(dir, faceIdxu);
  113. // Compute atlas tile
  114. atlasTiles >>= uvec2(faceIdxu * 5u);
  115. atlasTiles &= uvec2(31u);
  116. // Compute UV
  117. uv = (uv + vec2(atlasTiles)) * tileSize;
  118. // Sample
  119. shadowFactor = textureLod(shadowMap, uv, 0.0).r;
  120. }
  121. return saturate(exp(ESM_CONSTANT * (shadowFactor - linearDepth)));
  122. }
  123. // Compute the cubemap texture lookup vector given the reflection vector (r) the radius squared of the probe (R2) and
  124. // the frag pos in sphere space (f)
  125. vec3 computeCubemapVecAccurate(in vec3 r, in float R2, in vec3 f)
  126. {
  127. // Compute the collision of the r to the inner part of the sphere
  128. // From now on we work on the sphere's space
  129. // Project the center of the sphere (it's zero now since we are in sphere space) in ray "f,r"
  130. vec3 p = f - r * dot(f, r);
  131. // The collision to the sphere is point x where x = p + T * r
  132. // Because of the pythagorean theorem: R^2 = dot(p, p) + dot(T * r, T * r)
  133. // solving for T, T = R / |p|
  134. // then x becomes x = sqrt(R^2 - dot(p, p)) * r + p;
  135. float pp = dot(p, p);
  136. pp = min(pp, R2);
  137. float sq = sqrt(R2 - pp);
  138. vec3 x = p + sq * r;
  139. return x;
  140. }
  141. // Cheap version of computeCubemapVecAccurate
  142. vec3 computeCubemapVecCheap(in vec3 r, in float R2, in vec3 f)
  143. {
  144. return r;
  145. }
  146. float computeAttenuationFactor(float lightRadius, vec3 frag2Light)
  147. {
  148. float fragLightDist = dot(frag2Light, frag2Light);
  149. float att = 1.0 - fragLightDist * lightRadius;
  150. att = max(0.0, att);
  151. return att * att;
  152. }
  153. #endif