lights_physical_pars_fragment.glsl.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. export default /* glsl */`
  2. struct PhysicalMaterial {
  3. vec3 diffuseColor;
  4. float specularRoughness;
  5. vec3 specularColor;
  6. #ifndef STANDARD
  7. float clearCoat;
  8. float clearCoatRoughness;
  9. #endif
  10. };
  11. #define MAXIMUM_SPECULAR_COEFFICIENT 0.16
  12. #define DEFAULT_SPECULAR_COEFFICIENT 0.04
  13. // Clear coat directional hemishperical reflectance (this approximation should be improved)
  14. float clearCoatDHRApprox( const in float roughness, const in float dotNL ) {
  15. return DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );
  16. }
  17. #if NUM_RECT_AREA_LIGHTS > 0
  18. void RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
  19. vec3 normal = geometry.normal;
  20. vec3 viewDir = geometry.viewDir;
  21. vec3 position = geometry.position;
  22. vec3 lightPos = rectAreaLight.position;
  23. vec3 halfWidth = rectAreaLight.halfWidth;
  24. vec3 halfHeight = rectAreaLight.halfHeight;
  25. vec3 lightColor = rectAreaLight.color;
  26. float roughness = material.specularRoughness;
  27. vec3 rectCoords[ 4 ];
  28. rectCoords[ 0 ] = lightPos + halfWidth - halfHeight; // counterclockwise; light shines in local neg z direction
  29. rectCoords[ 1 ] = lightPos - halfWidth - halfHeight;
  30. rectCoords[ 2 ] = lightPos - halfWidth + halfHeight;
  31. rectCoords[ 3 ] = lightPos + halfWidth + halfHeight;
  32. vec2 uv = LTC_Uv( normal, viewDir, roughness );
  33. vec4 t1 = texture2D( ltc_1, uv );
  34. vec4 t2 = texture2D( ltc_2, uv );
  35. mat3 mInv = mat3(
  36. vec3( t1.x, 0, t1.y ),
  37. vec3( 0, 1, 0 ),
  38. vec3( t1.z, 0, t1.w )
  39. );
  40. // LTC Fresnel Approximation by Stephen Hill
  41. // http://blog.selfshadow.com/publications/s2016-advances/s2016_ltc_fresnel.pdf
  42. vec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );
  43. reflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );
  44. reflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );
  45. }
  46. #endif
  47. void RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
  48. float dotNL = saturate( dot( geometry.normal, directLight.direction ) );
  49. vec3 irradiance = dotNL * directLight.color;
  50. #ifndef PHYSICALLY_CORRECT_LIGHTS
  51. irradiance *= PI; // punctual light
  52. #endif
  53. #ifndef STANDARD
  54. float clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );
  55. #else
  56. float clearCoatDHR = 0.0;
  57. #endif
  58. reflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );
  59. reflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
  60. #ifndef STANDARD
  61. reflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );
  62. #endif
  63. }
  64. void RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {
  65. // Defer to the IndirectSpecular function to compute
  66. // the indirectDiffuse if energy preservation is enabled.
  67. #ifndef ENERGY_PRESERVATION
  68. reflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );
  69. #endif
  70. }
  71. void RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {
  72. #ifndef STANDARD
  73. float dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );
  74. float dotNL = dotNV;
  75. float clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );
  76. #else
  77. float clearCoatDHR = 0.0;
  78. #endif
  79. float clearCoatInv = 1.0 - clearCoatDHR;
  80. // Both indirect specular and diffuse light accumulate here
  81. // if energy preservation enabled, and PMREM provided.
  82. #if defined( ENERGY_PRESERVATION )
  83. vec3 singleScattering = vec3( 0.0 );
  84. vec3 multiScattering = vec3( 0.0 );
  85. vec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;
  86. BRDF_Specular_Multiscattering_Environment( geometry, material.specularColor, material.specularRoughness, singleScattering, multiScattering );
  87. vec3 diffuse = material.diffuseColor * ( 1.0 - ( singleScattering + multiScattering ) );
  88. reflectedLight.indirectSpecular += clearCoatInv * radiance * singleScattering;
  89. reflectedLight.indirectDiffuse += multiScattering * cosineWeightedIrradiance;
  90. reflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;
  91. #else
  92. reflectedLight.indirectSpecular += clearCoatInv * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );
  93. #endif
  94. #ifndef STANDARD
  95. reflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );
  96. #endif
  97. }
  98. #define RE_Direct RE_Direct_Physical
  99. #define RE_Direct_RectArea RE_Direct_RectArea_Physical
  100. #define RE_IndirectDiffuse RE_IndirectDiffuse_Physical
  101. #define RE_IndirectSpecular RE_IndirectSpecular_Physical
  102. #define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )
  103. #define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )
  104. // ref: https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf
  105. float computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {
  106. return saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );
  107. }
  108. `;