pbrDirectLightingFalloffFunctions.fx 4.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. float computeDistanceLightFalloff_Standard(vec3 lightOffset, float range)
  2. {
  3. return max(0., 1.0 - length(lightOffset) / range);
  4. }
  5. float computeDistanceLightFalloff_Physical(float lightDistanceSquared)
  6. {
  7. return 1.0 / maxEps(lightDistanceSquared);
  8. }
  9. float computeDistanceLightFalloff_GLTF(float lightDistanceSquared, float inverseSquaredRange)
  10. {
  11. float lightDistanceFalloff = 1.0 / maxEps(lightDistanceSquared);
  12. float factor = lightDistanceSquared * inverseSquaredRange;
  13. float attenuation = saturate(1.0 - factor * factor);
  14. attenuation *= attenuation;
  15. // Smooth attenuation of the falloff defined by the range.
  16. lightDistanceFalloff *= attenuation;
  17. return lightDistanceFalloff;
  18. }
  19. float computeDistanceLightFalloff(vec3 lightOffset, float lightDistanceSquared, float range, float inverseSquaredRange)
  20. {
  21. #ifdef USEPHYSICALLIGHTFALLOFF
  22. return computeDistanceLightFalloff_Physical(lightDistanceSquared);
  23. #elif defined(USEGLTFLIGHTFALLOFF)
  24. return computeDistanceLightFalloff_GLTF(lightDistanceSquared, inverseSquaredRange);
  25. #else
  26. return computeDistanceLightFalloff_Standard(lightOffset, range);
  27. #endif
  28. }
  29. float computeDirectionalLightFalloff_Standard(vec3 lightDirection, vec3 directionToLightCenterW, float cosHalfAngle, float exponent)
  30. {
  31. float falloff = 0.0;
  32. float cosAngle = maxEps(dot(-lightDirection, directionToLightCenterW));
  33. if (cosAngle >= cosHalfAngle)
  34. {
  35. falloff = max(0., pow(cosAngle, exponent));
  36. }
  37. return falloff;
  38. }
  39. float computeDirectionalLightFalloff_Physical(vec3 lightDirection, vec3 directionToLightCenterW, float cosHalfAngle)
  40. {
  41. const float kMinusLog2ConeAngleIntensityRatio = 6.64385618977; // -log2(0.01)
  42. // Calculate a Spherical Gaussian (von Mises-Fisher distribution, not angle-based Gaussian) such that the peak is in the light direction,
  43. // and the value at the nominal cone angle is 1% of the peak. Because we want the distribution to decay from unity (100%)
  44. // at the peak direction (dot product = 1) down to 1% at the nominal cone cutoff (dot product = cosAngle)
  45. // the falloff rate expressed in terms of the base-two dot product is therefore -log2(ConeAngleIntensityRatio) / (1.0 - cosAngle).
  46. // Note that the distribution is unnormalised in that peak density is unity, rather than the total energy is unity.
  47. float concentrationKappa = kMinusLog2ConeAngleIntensityRatio / (1.0 - cosHalfAngle);
  48. // Evaluate spherical gaussian for light directional falloff for spot light type (note: spot directional falloff;
  49. // not directional light type)
  50. vec4 lightDirectionSpreadSG = vec4(-lightDirection * concentrationKappa, -concentrationKappa);
  51. float falloff = exp2(dot(vec4(directionToLightCenterW, 1.0), lightDirectionSpreadSG));
  52. return falloff;
  53. }
  54. float computeDirectionalLightFalloff_GLTF(vec3 lightDirection, vec3 directionToLightCenterW, float lightAngleScale, float lightAngleOffset)
  55. {
  56. // On the CPU
  57. // float lightAngleScale = 1.0 f / max (0.001f, ( cosInner - cosOuter ));
  58. // float lightAngleOffset = -cosOuter * angleScale;
  59. float cd = dot(-lightDirection, directionToLightCenterW);
  60. float falloff = saturate(cd * lightAngleScale + lightAngleOffset);
  61. // smooth the transition
  62. falloff *= falloff;
  63. return falloff;
  64. }
  65. float computeDirectionalLightFalloff(vec3 lightDirection, vec3 directionToLightCenterW, float cosHalfAngle, float exponent, float lightAngleScale, float lightAngleOffset)
  66. {
  67. #ifdef USEPHYSICALLIGHTFALLOFF
  68. return computeDirectionalLightFalloff_Physical(lightDirection, directionToLightCenterW, cosHalfAngle);
  69. #elif defined(USEGLTFLIGHTFALLOFF)
  70. return computeDirectionalLightFalloff_GLTF(lightDirection, directionToLightCenterW, lightAngleScale, lightAngleOffset);
  71. #else
  72. return computeDirectionalLightFalloff_Standard(lightDirection, directionToLightCenterW, cosHalfAngle, exponent);
  73. #endif
  74. }