@@ -1283,14 +1283,19 @@ var standard = {
1283
1283
}
1284
1284
var useOldAmbient = false ;
1285
1285
if ( options . useSpecular ) {
1286
- if ( lighting ) code += options . shadingModel === SPECULAR_PHONG ? chunks . lightSpecularPhongPS : ( options . enableGGXSpecular ) ? chunks . lightSpecularAnisoGGXPS : chunks . lightSpecularBlinnPS ;
1286
+ if ( lighting ) {
1287
+ // used for energy conservation and to modulate specular with half-angle fresnel
1288
+ code += "vec3 dLightFresnel;\n" ;
1289
+ code += "vec3 ccLightFresnel;\n\n" ;
1290
+
1291
+ code += options . shadingModel === SPECULAR_PHONG ? chunks . lightSpecularPhongPS : ( options . enableGGXSpecular ) ? chunks . lightSpecularAnisoGGXPS : chunks . lightSpecularBlinnPS ;
1292
+ }
1287
1293
if ( options . sphereMap || cubemapReflection || options . dpAtlas || ( options . fresnelModel > 0 ) ) {
1288
1294
if ( options . fresnelModel > 0 ) {
1289
- if ( options . conserveEnergy && ! hasAreaLights ) {
1290
- // NB if there are area lights, energy conservation is done differently
1291
- code += chunks . combineDiffuseSpecularPS ; // this one is correct, others are old stuff
1295
+ if ( options . conserveEnergy && ! options . useMetalness ) {
1296
+ code += chunks . combineDiffuseSpecularPS ; // post half-angle fresnel, this one is for spec-gloss path
1292
1297
} else {
1293
- code += chunks . combineDiffuseSpecularNoConservePS ; // if you don't use environment cubemaps, you may consider this
1298
+ code += chunks . combineDiffuseSpecularNoConservePS ; // post half-angle fresnel, this one is for metalness-gloss path
1294
1299
}
1295
1300
} else {
1296
1301
code += chunks . combineDiffuseSpecularOldPS ;
@@ -1459,17 +1464,7 @@ var standard = {
1459
1464
code += " getSpecularity();\n" ;
1460
1465
if ( ! getGlossinessCalled ) code += " getGlossiness();\n" ;
1461
1466
1462
- // this is needed to allow custom area light fresnel calculations
1463
- if ( hasAreaLights ) {
1464
- code += " #ifdef AREA_LIGHTS\n" ;
1465
- code += " dSpecularityNoFres = dSpecularity;\n" ;
1466
- code += " #ifdef CLEARCOAT\n" ;
1467
- code += " ccSpecularityNoFres = ccSpecularity;\n" ;
1468
- code += " #endif\n" ;
1469
- code += " #endif\n" ;
1470
- }
1471
-
1472
- if ( ! options . useMetalness && options . fresnelModel > 0 ) code += " getFresnel();\n" ;
1467
+ // NB switched to more correct half-angle fresnel
1473
1468
}
1474
1469
1475
1470
if ( addAmbient ) {
@@ -1493,14 +1488,9 @@ var standard = {
1493
1488
code += " addReflection();\n" ;
1494
1489
}
1495
1490
1496
- if ( options . useSpecular && options . useMetalness && options . fresnelModel > 0 ) code += " getFresnel();\n" ;
1491
+ // NB switched to more correct half-angle fresnel
1497
1492
1498
1493
if ( hasAreaLights ) {
1499
- // specular has to be accumulated differently if we want area lights to look correct
1500
- code += " ccReflection.rgb *= ccSpecularity;\n" ;
1501
- code += " dReflection.rgb *= dSpecularity;\n" ;
1502
- code += " dSpecularLight *= dSpecularity;\n" ;
1503
-
1504
1494
code += " float roughness = max((1.0 - dGlossiness) * (1.0 - dGlossiness), 0.001);\n" ;
1505
1495
}
1506
1496
@@ -1650,34 +1640,25 @@ var standard = {
1650
1640
}
1651
1641
}
1652
1642
1643
+ // NB specular lighting moved here for legacy energy conservation
1644
+ if ( options . clearCoat > 0 ) code += " ccSpecularLight += get" + shapeString + "LightSpecularCC() * dAtten * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ";\n" ;
1645
+ if ( options . useSpecular ) code += " dSpecularLight += get" + shapeString + "LightSpecular() * dAtten * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ";\n" ;
1646
+
1653
1647
// non-punctual lights do not mix diffuse lighting into specular attenuation
1654
1648
if ( lightShape !== LIGHTSHAPE_PUNCTUAL ) {
1655
- if ( options . conserveEnergy && options . useSpecular ) {
1656
- code += " dDiffuseLight += mix((dAttenD * dAtten) * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ", vec3(0), dLTCSpecFres );\n" ;
1649
+ if ( options . conserveEnergy && options . useSpecular && ! options . useMetalness ) {
1650
+ code += " dDiffuseLight += mix((dAttenD * dAtten) * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ", vec3(0), dLightFresnel * dSpecularity );\n" ;
1657
1651
} else {
1658
1652
code += " dDiffuseLight += (dAttenD * dAtten) * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ";\n" ;
1659
1653
}
1660
1654
} else {
1661
- if ( hasAreaLights && options . conserveEnergy && options . useSpecular ) {
1662
- code += " dDiffuseLight += mix(dAtten * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ", vec3(0), dSpecularity);\n" ;
1655
+ if ( options . conserveEnergy && options . useSpecular && ! options . useMetalness ) {
1656
+ code += " dDiffuseLight += mix(dAtten * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ", vec3(0), dLightFresnel * dSpecularity);\n" ;
1663
1657
} else {
1664
1658
code += " dDiffuseLight += dAtten * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ";\n" ;
1665
1659
}
1666
1660
}
1667
1661
1668
- if ( lightShape !== LIGHTSHAPE_PUNCTUAL ) {
1669
- if ( options . clearCoat > 0 ) code += " ccSpecularLight += ccLTCSpecFres * get" + shapeString + "LightSpecularCC() * dAtten * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ";\n" ;
1670
- if ( options . useSpecular ) code += " dSpecularLight += dLTCSpecFres * get" + shapeString + "LightSpecular() * dAtten * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ";\n" ;
1671
- } else {
1672
- if ( hasAreaLights ) {
1673
- // if LTC lights are present, specular must be accumulated with specularity (specularity is pre multiplied by punctual light fresnel)
1674
- if ( options . clearCoat > 0 ) code += " ccSpecularLight += ccSpecularity * getLightSpecularCC() * dAtten * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ";\n" ;
1675
- if ( options . useSpecular ) code += " dSpecularLight += dSpecularity * getLightSpecular() * dAtten * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ";\n" ;
1676
- } else {
1677
- if ( options . clearCoat > 0 ) code += " ccSpecularLight += getLightSpecularCC() * dAtten * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ";\n" ;
1678
- if ( options . useSpecular ) code += " dSpecularLight += getLightSpecular() * dAtten * light" + i + "_color" + ( usesCookieNow ? " * dAtten3" : "" ) + ";\n" ;
1679
- }
1680
- }
1681
1662
1682
1663
if ( lightType !== LIGHTTYPE_DIRECTIONAL ) {
1683
1664
code += " }\n" ; // BRANCH END
@@ -1686,15 +1667,7 @@ var standard = {
1686
1667
code += "\n" ;
1687
1668
}
1688
1669
1689
- if ( hasAreaLights ) {
1690
- // specular has to be accumulated differently if we want area lights to look correct
1691
- if ( options . clearCoat > 0 ) {
1692
- code += " ccSpecularity = 1.0;\n" ;
1693
- }
1694
- if ( options . useSpecular ) {
1695
- code += " dSpecularity = vec3(1);\n" ;
1696
- }
1697
- }
1670
+ // NB using half-angle fresnel accumulates specular consistenetly accross all punctual, area and image-based lights
1698
1671
1699
1672
if ( ( cubemapReflection || options . sphereMap || options . dpAtlas ) && options . refraction ) {
1700
1673
code += " addRefraction();\n" ;
@@ -1770,7 +1743,6 @@ var standard = {
1770
1743
if ( code . includes ( "dShadowCoord" ) ) structCode += "vec3 dShadowCoord;\n" ;
1771
1744
if ( code . includes ( "dNormalMap" ) ) structCode += "vec3 dNormalMap;\n" ;
1772
1745
if ( code . includes ( "dSpecularity" ) ) structCode += "vec3 dSpecularity;\n" ;
1773
- if ( code . includes ( "dSpecularityNoFres" ) ) structCode += "vec3 dSpecularityNoFres;\n" ;
1774
1746
if ( code . includes ( "dUvOffset" ) ) structCode += "vec2 dUvOffset;\n" ;
1775
1747
if ( code . includes ( "dGlossiness" ) ) structCode += "float dGlossiness;\n" ;
1776
1748
if ( code . includes ( "dAlpha" ) ) structCode += "float dAlpha;\n" ;
@@ -1784,7 +1756,6 @@ var standard = {
1784
1756
if ( code . includes ( "ccReflDirW" ) ) structCode += "vec3 ccReflDirW;\n" ;
1785
1757
if ( code . includes ( "ccSpecularLight" ) ) structCode += "vec3 ccSpecularLight;\n" ;
1786
1758
if ( code . includes ( "ccSpecularity" ) ) structCode += "float ccSpecularity;\n" ;
1787
- if ( code . includes ( "ccSpecularityNoFres" ) ) structCode += "float ccSpecularityNoFres;\n" ;
1788
1759
if ( code . includes ( "ccGlossiness" ) ) structCode += "float ccGlossiness;\n" ;
1789
1760
1790
1761
code = codeBegin + structCode + code ;
0 commit comments