LightFunctions.glsl 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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 functions for light calculations
  6. #ifndef ANKI_SHADERS_LIGHT_FUNCTIONS_GLSL
  7. #define ANKI_SHADERS_LIGHT_FUNCTIONS_GLSL
  8. #pragma anki include "shaders/Common.glsl"
  9. const float ATTENUATION_BOOST = 0.05;
  10. const float OMNI_LIGHT_FRUSTUM_NEAR_PLANE = 0.1 / 4.0;
  11. const uint SHADOW_SAMPLE_COUNT = 16;
  12. //==============================================================================
  13. float computeAttenuationFactor(float lightRadius, vec3 frag2Light)
  14. {
  15. float fragLightDist = dot(frag2Light, frag2Light);
  16. float att = 1.0 - fragLightDist * lightRadius;
  17. att = max(0.0, att);
  18. return att * att;
  19. }
  20. //==============================================================================
  21. // Performs BRDF specular lighting
  22. vec3 computeSpecularColorBrdf(
  23. vec3 v, // view dir
  24. vec3 l, // light dir
  25. vec3 n, // normal
  26. vec3 specCol,
  27. vec3 lightSpecCol,
  28. float a2, // rougness^2
  29. float nol) // N dot L
  30. {
  31. vec3 h = normalize(l + v);
  32. // Fresnel
  33. float voh = max(EPSILON, dot(v, h));
  34. #if 0
  35. // Schlick
  36. vec3 F = specCol + (1.0 - specCol) * pow((1.0 + EPSILON - loh), 5.0);
  37. #else
  38. // Unreal
  39. vec3 F = specCol + (1.0 - specCol)
  40. * pow(2.0, (-5.55473 * voh - 6.98316) * voh);
  41. #endif
  42. // D(n,h) aka NDF: GGX Trowbridge-Reitz
  43. float noh = max(EPSILON, dot(n, h));
  44. float D = noh * noh * (a2 - 1.0) + 1.0;
  45. D = a2 / (PI * D * D);
  46. // G(l,v,h)/(4*dot(n,h)*dot(n,v)) aka Visibility term: Geometric shadowing
  47. // divided by BRDF denominator
  48. #if 0
  49. float nov = max(EPSILON, dot(n, v));
  50. float V_v = nov + sqrt((nov - nov * a2) * nov + a2);
  51. float V_l = nol + sqrt((nol - nol * a2) * nol + a2);
  52. float V = 1.0 / (V_l * V_v);
  53. #else
  54. float k = (a2 + 1.0);
  55. k = k * k / 8.0;
  56. float nov = max(EPSILON, dot(n, v));
  57. float V_v = nov * (1.0 - k) + k;
  58. float V_l = nol * (1.0 - k) + k;
  59. float V = 1.0 / (4.0 * V_l * V_v);
  60. #endif
  61. return F * (V * D) * lightSpecCol;
  62. }
  63. //==============================================================================
  64. vec3 computeDiffuseColor(vec3 diffCol, vec3 lightDiffCol)
  65. {
  66. return diffCol * lightDiffCol;
  67. }
  68. //==============================================================================
  69. float computeSpotFactor(
  70. vec3 l,
  71. float outerCos,
  72. float innerCos,
  73. vec3 spotDir)
  74. {
  75. float costheta = -dot(l, spotDir);
  76. float spotFactor = smoothstep(outerCos, innerCos, costheta);
  77. return spotFactor;
  78. }
  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. //==============================================================================
  90. float computeShadowFactorSpot(mat4 lightProjectionMat, vec3 fragPos,
  91. float layer, uint sampleCount)
  92. {
  93. vec4 texCoords4 = lightProjectionMat * vec4(fragPos, 1.0);
  94. vec3 texCoords3 = texCoords4.xyz / texCoords4.w;
  95. #if POISSON == 1
  96. const vec2 poissonDisk[SHADOW_SAMPLE_COUNT] = vec2[](
  97. vec2(0.751688, 0.619709) * 2.0 - 1.0,
  98. vec2(0.604741, 0.778485) * 2.0 - 1.0,
  99. vec2(0.936216, 0.463094) * 2.0 - 1.0,
  100. vec2(0.808758, 0.284966) * 2.0 - 1.0,
  101. vec2(0.812927, 0.786332) * 2.0 - 1.0,
  102. vec2(0.608651, 0.303919) * 2.0 - 1.0,
  103. vec2(0.482117, 0.573285) * 2.0 - 1.0,
  104. vec2(0.55819, 0.988451) * 2.0 - 1.0,
  105. vec2(0.340001, 0.728732) * 2.0 - 1.0,
  106. vec2(0.681775, 0.119789) * 2.0 - 1.0,
  107. vec2(0.217429, 0.522558) * 2.0 - 1.0,
  108. vec2(0.384257, 0.352163) * 2.0 - 1.0,
  109. vec2(0.143769, 0.738606) * 2.0 - 1.0,
  110. vec2(0.383474, 0.910019) * 2.0 - 1.0,
  111. vec2(0.409305, 0.177022) * 2.0 - 1.0,
  112. vec2(0.158647, 0.239097) * 2.0 - 1.0);
  113. float shadowFactor = 0.0;
  114. vec2 cordpart0 = vec2(layer, texCoords3.z);
  115. for(uint i = 0; i < sampleCount; i++)
  116. {
  117. vec2 cordpart1 = texCoords3.xy + poissonDisk[i] / 512.0;
  118. vec4 tcoord = vec4(cordpart1, cordpart0);
  119. shadowFactor += texture(u_spotMapArr, tcoord);
  120. }
  121. return shadowFactor / float(sampleCount);
  122. #else
  123. vec4 tcoord = vec4(texCoords3.x, texCoords3.y, layer, texCoords3.z);
  124. float shadowFactor = texture(u_spotMapArr, tcoord);
  125. return shadowFactor;
  126. #endif
  127. }
  128. //==============================================================================
  129. float computeShadowFactorOmni(vec3 frag2Light, float layer, float radius)
  130. {
  131. vec3 dir = (u_lightingUniforms.viewMat * vec4(-frag2Light, 1.0)).xyz;
  132. vec3 dirabs = abs(dir);
  133. float dist = -max(dirabs.x, max(dirabs.y, dirabs.z));
  134. dir = normalize(dir);
  135. const float near = OMNI_LIGHT_FRUSTUM_NEAR_PLANE;
  136. const float far = radius;
  137. // Original code:
  138. // float g = near - far;
  139. // float z = (far + near) / g * dist + (2.0 * far * near) / g;
  140. // float w = -dist;
  141. // z /= w;
  142. // z = z * 0.5 + 0.5;
  143. // Optimized:
  144. float z = (far * (dist + near)) / (dist * (far - near));
  145. float shadowFactor = texture(u_omniMapArr, vec4(dir, layer), z).r;
  146. return shadowFactor;
  147. }
  148. #endif