pbrFalloffLightingFunctions.fx 4.1 KB

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