@@ -12,8 +12,7 @@ import { diffuseColor, diffuseContribution, specularColor, specularColorBlended,
1212import { normalView , clearcoatNormalView , normalWorld } from '../accessors/Normal.js' ;
1313import { positionViewDirection , positionView , positionWorld } from '../accessors/Position.js' ;
1414import { Fn , float , vec2 , vec3 , vec4 , mat3 , If } from '../tsl/TSLBase.js' ;
15- import { select } from '../math/ConditionalNode.js' ;
16- import { mix , normalize , refract , length , clamp , log2 , log , exp , smoothstep } from '../math/MathNode.js' ;
15+ import { mix , normalize , refract , length , clamp , log2 , log , exp , smoothstep , inverseSqrt } from '../math/MathNode.js' ;
1716import { div } from '../math/OperatorNode.js' ;
1817import { cameraPosition , cameraProjectionMatrix , cameraViewMatrix } from '../accessors/Camera.js' ;
1918import { modelWorldMatrix } from '../accessors/ModelNode.js' ;
@@ -313,29 +312,26 @@ const evalIridescence = /*@__PURE__*/ Fn( ( { outsideIOR, eta2, cosTheta1, thinF
313312//
314313
315314// This is a curve-fit approximation to the "Charlie sheen" BRDF integrated over the hemisphere from
316- // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF". The analysis can be found
317- // in the Sheen section of https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing
315+ // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF".
316+ // The low roughness fit (< 0.25) uses an inversesqrt/log model to accurately capture the sharp peak.
318317const IBLSheenBRDF = /*@__PURE__ */ Fn ( ( { normal, viewDir, roughness } ) => {
319318
320319 const dotNV = normal . dot ( viewDir ) . saturate ( ) ;
320+ const r2 = roughness . mul ( roughness ) ;
321321
322- const r2 = roughness . pow2 ( ) ;
323-
324- const a = select (
325- roughness . lessThan ( 0.25 ) ,
326- float ( - 339.2 ) . mul ( r2 ) . add ( float ( 161.4 ) . mul ( roughness ) ) . sub ( 25.9 ) ,
327- float ( - 8.48 ) . mul ( r2 ) . add ( float ( 14.3 ) . mul ( roughness ) ) . sub ( 9.95 )
322+ const a = roughness . lessThan ( 0.25 ) . select (
323+ inverseSqrt ( roughness ) . mul ( - 1.57 ) ,
324+ r2 . mul ( - 3.33 ) . add ( roughness . mul ( 6.27 ) ) . sub ( 4.40 )
328325 ) ;
329326
330- const b = select (
331- roughness . lessThan ( 0.25 ) ,
332- float ( 44.0 ) . mul ( r2 ) . sub ( float ( 23.7 ) . mul ( roughness ) ) . add ( 3.26 ) ,
333- float ( 1.97 ) . mul ( r2 ) . sub ( float ( 3.27 ) . mul ( roughness ) ) . add ( 0.72 )
327+ const b = roughness . lessThan ( 0.25 ) . select (
328+ log ( roughness ) . mul ( - 0.46 ) . sub ( 0.64 ) ,
329+ r2 . mul ( 0.92 ) . sub ( roughness . mul ( 1.79 ) ) . add ( 0.35 )
334330 ) ;
335331
336- const DG = select ( roughness . lessThan ( 0.25 ) , 0.0 , float ( 0.1 ) . mul ( roughness ) . sub ( 0.025 ) ) . add ( a . mul ( dotNV ) . add ( b ) . exp ( ) ) ;
332+ const DG = a . mul ( dotNV ) . add ( b ) . exp ( ) ;
337333
338- return DG . mul ( 1.0 / Math . PI ) . saturate ( ) ;
334+ return DG . saturate ( ) ;
339335
340336} ) ;
341337
@@ -608,12 +604,19 @@ class PhysicalLightingModel extends LightingModel {
608604 direct ( { lightDirection, lightColor, reflectedLight } , /* builder */ ) {
609605
610606 const dotNL = normalView . dot ( lightDirection ) . clamp ( ) ;
611- const irradiance = dotNL . mul ( lightColor ) ;
607+ const irradiance = dotNL . mul ( lightColor ) . toVar ( ) ;
612608
613609 if ( this . sheen === true ) {
614610
615611 this . sheenSpecularDirect . addAssign ( irradiance . mul ( BRDF_Sheen ( { lightDirection } ) ) ) ;
616612
613+ const sheenAlbedoV = IBLSheenBRDF ( { normal : normalView , viewDir : positionViewDirection , roughness : sheenRoughness } ) ;
614+ const sheenAlbedoL = IBLSheenBRDF ( { normal : normalView , viewDir : lightDirection , roughness : sheenRoughness } ) ;
615+
616+ const sheenEnergyComp = sheen . r . max ( sheen . g ) . max ( sheen . b ) . mul ( sheenAlbedoV . max ( sheenAlbedoL ) ) . oneMinus ( ) ;
617+
618+ irradiance . mulAssign ( sheenEnergyComp ) ;
619+
617620 }
618621
619622 if ( this . clearcoat === true ) {
@@ -692,7 +695,19 @@ class PhysicalLightingModel extends LightingModel {
692695
693696 const { irradiance, reflectedLight } = builder . context ;
694697
695- reflectedLight . indirectDiffuse . addAssign ( irradiance . mul ( BRDF_Lambert ( { diffuseColor : diffuseContribution } ) ) ) ;
698+ const diffuse = irradiance . mul ( BRDF_Lambert ( { diffuseColor : diffuseContribution } ) ) . toVar ( ) ;
699+
700+ if ( this . sheen === true ) {
701+
702+ const sheenAlbedo = IBLSheenBRDF ( { normal : normalView , viewDir : positionViewDirection , roughness : sheenRoughness } ) ;
703+
704+ const sheenEnergyComp = sheen . r . max ( sheen . g ) . max ( sheen . b ) . mul ( sheenAlbedo ) . oneMinus ( ) ;
705+
706+ diffuse . mulAssign ( sheenEnergyComp ) ;
707+
708+ }
709+
710+ reflectedLight . indirectDiffuse . addAssign ( diffuse ) ;
696711
697712 }
698713
@@ -755,10 +770,23 @@ class PhysicalLightingModel extends LightingModel {
755770
756771 const cosineWeightedIrradiance = iblIrradiance . mul ( 1 / Math . PI ) ;
757772
758- reflectedLight . indirectSpecular . addAssign ( radiance . mul ( singleScattering ) ) ;
759- reflectedLight . indirectSpecular . addAssign ( multiScattering . mul ( cosineWeightedIrradiance ) ) ;
773+ const indirectSpecular = radiance . mul ( singleScattering ) . add ( multiScattering . mul ( cosineWeightedIrradiance ) ) . toVar ( ) ;
774+ const indirectDiffuse = diffuse . mul ( cosineWeightedIrradiance ) . toVar ( ) ;
775+
776+ if ( this . sheen === true ) {
777+
778+ const sheenAlbedo = IBLSheenBRDF ( { normal : normalView , viewDir : positionViewDirection , roughness : sheenRoughness } ) ;
779+
780+ const sheenEnergyComp = sheen . r . max ( sheen . g ) . max ( sheen . b ) . mul ( sheenAlbedo ) . oneMinus ( ) ;
781+
782+ indirectSpecular . mulAssign ( sheenEnergyComp ) ;
783+ indirectDiffuse . mulAssign ( sheenEnergyComp ) ;
784+
785+ }
786+
787+ reflectedLight . indirectSpecular . addAssign ( indirectSpecular ) ;
760788
761- reflectedLight . indirectDiffuse . addAssign ( diffuse . mul ( cosineWeightedIrradiance ) ) ;
789+ reflectedLight . indirectDiffuse . addAssign ( indirectDiffuse ) ;
762790
763791 }
764792
@@ -822,10 +850,9 @@ class PhysicalLightingModel extends LightingModel {
822850
823851 if ( this . sheen === true ) {
824852
825- const sheenEnergyComp = sheen . r . max ( sheen . g ) . max ( sheen . b ) . mul ( 0.157 ) . oneMinus ( ) ;
826- const sheenLight = outgoingLight . mul ( sheenEnergyComp ) . add ( this . sheenSpecularDirect , this . sheenSpecularIndirect ) ;
853+ const sheenLight = outgoingLight . add ( this . sheenSpecularDirect , this . sheenSpecularIndirect . mul ( 1.0 / Math . PI ) ) ;
827854
828- outgoingLight . assign ( sheenLight ) ;
855+ outgoingLight . assign ( sheenLight ) ;
829856
830857 }
831858
0 commit comments