lights_physical_pars_fragment.glsl.js 5.8 KB

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