LightFunctions.glsl 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Copyright (C) 2009-2017, 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. const float LIGHT_FRUSTUM_NEAR_PLANE = 0.1 / 4.0;
  10. const uint SHADOW_SAMPLE_COUNT = 16;
  11. const float ESM_CONSTANT = 40.0;
  12. float computeAttenuationFactor(float lightRadius, vec3 frag2Light)
  13. {
  14. float fragLightDist = dot(frag2Light, frag2Light);
  15. float att = 1.0 - fragLightDist * lightRadius;
  16. att = max(0.0, att);
  17. return att * att;
  18. }
  19. // Performs BRDF specular lighting
  20. vec3 computeSpecularColorBrdf(vec3 v, // view dir
  21. vec3 l, // light dir
  22. vec3 n, // normal
  23. vec3 specCol,
  24. vec3 lightSpecCol,
  25. float a2, // rougness^2
  26. float nol) // N dot L
  27. {
  28. vec3 h = normalize(l + v);
  29. // Fresnel
  30. float voh = dot(v, h);
  31. #if 0
  32. // Schlick
  33. vec3 F = specCol + (1.0 - specCol) * pow((1.0 + EPSILON - loh), 5.0);
  34. #else
  35. // Unreal
  36. vec3 F = specCol + (1.0 - specCol) * pow(2.0, (-5.55473 * voh - 6.98316) * voh);
  37. #endif
  38. // D(n,h) aka NDF: GGX Trowbridge-Reitz
  39. float noh = dot(n, h);
  40. float D = noh * noh * (a2 - 1.0) + 1.0;
  41. D = a2 / (PI * D * D);
  42. // G(l,v,h)/(4*dot(n,h)*dot(n,v)) aka Visibility term: Geometric shadowing divided by BRDF denominator
  43. #if 0
  44. float nov = max(EPSILON, dot(n, v));
  45. float V_v = nov + sqrt((nov - nov * a2) * nov + a2);
  46. float V_l = nol + sqrt((nol - nol * a2) * nol + a2);
  47. float V = 1.0 / (V_l * V_v);
  48. #else
  49. float k = (a2 + 1.0);
  50. k = k * k / 8.0;
  51. float nov = max(EPSILON, dot(n, v));
  52. float V_v = nov * (1.0 - k) + k;
  53. float V_l = nol * (1.0 - k) + k;
  54. float V = 1.0 / (4.0 * V_l * V_v);
  55. #endif
  56. return F * (V * D) * lightSpecCol;
  57. }
  58. vec3 computeDiffuseColor(vec3 diffCol, vec3 lightDiffCol)
  59. {
  60. return diffCol * lightDiffCol;
  61. }
  62. float computeSpotFactor(vec3 l, float outerCos, float innerCos, vec3 spotDir)
  63. {
  64. float costheta = -dot(l, spotDir);
  65. float spotFactor = smoothstep(outerCos, innerCos, costheta);
  66. return spotFactor;
  67. }
  68. uint computeShadowSampleCount(const uint COUNT, float zVSpace)
  69. {
  70. const float MAX_DISTANCE = 5.0;
  71. float z = max(zVSpace, -MAX_DISTANCE);
  72. float sampleCountf = float(COUNT) + z * (float(COUNT) / MAX_DISTANCE);
  73. sampleCountf = max(sampleCountf, 1.0);
  74. uint sampleCount = uint(sampleCountf);
  75. return sampleCount;
  76. }
  77. float computeShadowFactorSpot(mat4 lightProjectionMat, vec3 fragPos, float distance, sampler2D spotMapArr)
  78. {
  79. vec4 texCoords4 = lightProjectionMat * vec4(fragPos, 1.0);
  80. vec3 texCoords3 = texCoords4.xyz / texCoords4.w;
  81. const float near = LIGHT_FRUSTUM_NEAR_PLANE;
  82. const float far = distance;
  83. float linearDepth = linearizeDepth(texCoords3.z, near, far);
  84. return clamp(exp(ESM_CONSTANT * (textureLod(spotMapArr, texCoords3.xy, 0.0).r - linearDepth)), 0.0, 1.0);
  85. }
  86. float computeShadowFactorOmni(
  87. vec3 frag2Light, float radius, mat3 invViewMat, uvec2 atlasTiles, float tileSize, sampler2D shadowMap)
  88. {
  89. vec3 dir = invViewMat * -frag2Light;
  90. vec3 dirabs = abs(dir);
  91. float dist = max(dirabs.x, max(dirabs.y, dirabs.z));
  92. const float near = LIGHT_FRUSTUM_NEAR_PLANE;
  93. const float far = radius;
  94. float linearDepth = (dist - near) / (far - near);
  95. // Read tex
  96. float shadowFactor;
  97. {
  98. // Convert cube coords
  99. uint faceIdxu;
  100. vec2 uv = convertCubeUvsu(dir, faceIdxu);
  101. // Compute atlas tile
  102. atlasTiles >>= uvec2(faceIdxu * 5u);
  103. atlasTiles &= uvec2(31u);
  104. // Compute UV
  105. uv = (uv + vec2(atlasTiles)) * tileSize;
  106. // Sample
  107. shadowFactor = textureLod(shadowMap, uv, 0.0).r;
  108. }
  109. return clamp(exp(ESM_CONSTANT * (shadowFactor - linearDepth)), 0.0, 1.0);
  110. }
  111. // Compute the cubemap texture lookup vector given the reflection vector (r) the radius squared of the probe (R2) and
  112. // the frag pos in sphere space (f)
  113. vec3 computeCubemapVecAccurate(in vec3 r, in float R2, in vec3 f)
  114. {
  115. // Compute the collision of the r to the inner part of the sphere
  116. // From now on we work on the sphere's space
  117. // Project the center of the sphere (it's zero now since we are in sphere space) in ray "f,r"
  118. vec3 p = f - r * dot(f, r);
  119. // The collision to the sphere is point x where x = p + T * r
  120. // Because of the pythagorean theorem: R^2 = dot(p, p) + dot(T * r, T * r)
  121. // solving for T, T = R / |p|
  122. // then x becomes x = sqrt(R^2 - dot(p, p)) * r + p;
  123. float pp = dot(p, p);
  124. pp = min(pp, R2);
  125. float sq = sqrt(R2 - pp);
  126. vec3 x = p + sq * r;
  127. return x;
  128. }
  129. // Cheap version of computeCubemapVecAccurate
  130. vec3 computeCubemapVecCheap(in vec3 r, in float R2, in vec3 f)
  131. {
  132. return r;
  133. }
  134. #endif