Skip to content

Commit d58f672

Browse files
Half angle fresnel (playcanvas#3172)
* global fresnel no longer affects reflections + f0 directly used by reflections * call envBrdf for all reflection types * spacing * all reflection types, when using metalness and f0, use envBrdf * Update examples/graphics/material-anisotropic.html Co-authored-by: Will Eastcott <will@playcanvas.com> * switch to GGX cubemap filtering * switch punctual lights to half angle fresnel * remove debug tmp code * lint Co-authored-by: Will Eastcott <will@playcanvas.com>
1 parent a00392b commit d58f672

12 files changed

+79
-101
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
vec3 combineColorCC() {
2-
return combineColor() + (ccSpecularLight * ccSpecularity + ccReflection.rgb * ccReflection.a);
2+
return combineColor() + (ccSpecularLight + ccReflection.rgb * ccReflection.a);
33
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
vec3 combineColor() {
2-
return mix(dAlbedo * dDiffuseLight, dSpecularLight, dSpecularity) + dReflection.rgb * dReflection.a;
2+
// NB energy conservation has changed with half-angle fresnel
3+
return dAlbedo * dDiffuseLight + dSpecularLight + dReflection.rgb * dReflection.a;
34
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
vec3 combineColor() {
2-
return dAlbedo * dDiffuseLight + (dSpecularLight * dSpecularity) + dReflection.rgb * dReflection.a;
2+
return dAlbedo * dDiffuseLight + dSpecularLight + dReflection.rgb * dReflection.a;
33
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
vec3 combineColor() {
2-
return dAlbedo * dDiffuseLight + dSpecularLight * dSpecularity;
2+
return dAlbedo * dDiffuseLight + dSpecularLight;
33
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
uniform vec3 material_ambient;
22

33
vec3 combineColor() {
4-
return (dDiffuseLight - light_globalAmbient) * dAlbedo + dSpecularLight * dSpecularity + material_ambient * light_globalAmbient;
4+
return (dDiffuseLight - light_globalAmbient) * dAlbedo + dSpecularLight + material_ambient * light_globalAmbient;
55
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
vec3 combineColor() {
2-
return mix(dAlbedo * dDiffuseLight + dSpecularLight * dSpecularity, dReflection.rgb, dReflection.a);
2+
return mix(dAlbedo * dDiffuseLight + dSpecularLight, dReflection.rgb, dReflection.a);
33
}
Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
// Schlick's approximation
2-
uniform float material_fresnelFactor; // unused
32

4-
void getFresnel() {
5-
float fresnel = 1.0 - max(dot(dNormalW, dViewDirW), 0.0);
6-
float fresnel2 = fresnel * fresnel;
7-
fresnel *= fresnel2 * fresnel2;
8-
fresnel *= dGlossiness * dGlossiness;
9-
dSpecularity = dSpecularity + (1.0 - dSpecularity) * fresnel;
3+
vec3 calcFresnel(float cosTheta, vec3 F0)
4+
{
5+
return F0 + (1.0 - F0) * pow(max(1.0 - cosTheta, 0.0), 5.0);
6+
}
107

11-
#ifdef CLEARCOAT
12-
fresnel = 1.0 - max(dot(ccNormalW, dViewDirW), 0.0);
13-
fresnel2 = fresnel * fresnel;
8+
vec3 calcFresnel(float cosTheta, vec3 F0, float glossiness)
9+
{
10+
float fresnel = 1.0 - cosTheta;
11+
float fresnel2 = fresnel * fresnel;
1412
fresnel *= fresnel2 * fresnel2;
15-
fresnel *= ccGlossiness * ccGlossiness;
16-
ccSpecularity = ccSpecularity + (1.0 - ccSpecularity) * fresnel;
17-
#endif
13+
fresnel *= glossiness * glossiness;
14+
return F0 + (1.0 - F0) * fresnel;
1815
}

src/graphics/program-lib/chunks/lightSpecularAnisoGGX.frag

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Anisotropic GGX
2-
float calcLightSpecular(float tGlossiness, vec3 tNormalW) {
2+
3+
vec3 calcLightSpecular(float tGlossiness, vec3 tNormalW, vec3 F0, out vec3 tFresnel) {
34
float PI = 3.141592653589793;
45
float roughness = max((1.0 - tGlossiness) * (1.0 - tGlossiness), 0.001);
56
float anisotropy = material_anisotropy * roughness;
@@ -30,13 +31,18 @@ float calcLightSpecular(float tGlossiness, vec3 tNormalW) {
3031
float lambdaL = NoV * length(vec3(at * ToL, ab * BoL, NoL));
3132
float G = 0.5 / (lambdaV + lambdaL);
3233

33-
return D * G;
34+
vec3 F = calcFresnel(NoH, F0);
35+
36+
tFresnel = F;
37+
38+
return D * G * F;
3439
}
3540

36-
float getLightSpecular() {
37-
return calcLightSpecular(dGlossiness, dNormalW);
41+
vec3 getLightSpecular() {
42+
return calcLightSpecular(dGlossiness, dNormalW, dSpecularity, dLightFresnel);
3843
}
3944

40-
float getLightSpecularCC() {
41-
return calcLightSpecular(ccGlossiness, ccNormalW);
45+
vec3 getLightSpecularCC() {
46+
47+
return calcLightSpecular(ccGlossiness, ccNormalW, vec3(ccSpecularity), ccLightFresnel);
4248
}
Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// Energy-conserving (hopefully) Blinn-Phong
2-
float calcLightSpecular(float tGlossiness, vec3 tNormalW) {
2+
vec3 calcLightSpecular(float tGlossiness, vec3 tNormalW, vec3 F0, out vec3 tFresnel) {
33
vec3 h = normalize( -dLightDirNormW + dViewDirW );
44
float nh = max( dot( h, tNormalW ), 0.0 );
55

@@ -9,13 +9,17 @@ float calcLightSpecular(float tGlossiness, vec3 tNormalW) {
99
// Hack: On Mac OS X, calling pow with zero for the exponent generates hideous artifacts so bias up a little
1010
specPow = max(specPow, 0.0001);
1111

12-
return pow(nh, specPow) * (specPow + 2.0) / 8.0;
12+
vec3 F = calcFresnel(nh, F0);
13+
14+
tFresnel = F;
15+
16+
return F * pow(nh, specPow) * (specPow + 2.0) / 8.0;
1317
}
1418

15-
float getLightSpecular() {
16-
return calcLightSpecular(dGlossiness, dNormalW);
19+
vec3 getLightSpecular() {
20+
return calcLightSpecular(dGlossiness, dNormalW, dSpecularity, dLightFresnel);
1721
}
1822

19-
float getLightSpecularCC() {
20-
return calcLightSpecular(ccGlossiness, ccNormalW);
23+
vec3 getLightSpecularCC() {
24+
return calcLightSpecular(ccGlossiness, ccNormalW, vec3(ccSpecularity), ccLightFresnel);
2125
}
Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
float calcLightSpecular(float tGlossiness, vec3 tReflDirW) {
1+
vec3 calcLightSpecular(float tGlossiness, vec3 tReflDirW, vec3 F0, out vec3 tFresnel) {
22
float specPow = tGlossiness;
33

44
specPow = antiAliasGlossiness(specPow);
55

6+
float rl = max(dot(tReflDirW, -dLightDirNormW), 0.0);
7+
8+
vec3 F = calcFresnel(rl, F0);
9+
610
// Hack: On Mac OS X, calling pow with zero for the exponent generates hideous artifacts so bias up a little
7-
return pow(max(dot(tReflDirW, -dLightDirNormW), 0.0), specPow + 0.0001);
11+
return F * pow(rl, specPow + 0.0001);
812
}
913

10-
float getLightSpecular() {
11-
return calcLightSpecular(dGlossiness, dReflDirW);
14+
vec3 getLightSpecular() {
15+
return calcLightSpecular(dGlossiness, dNormalW, dSpecularity, dLightFresnel);
1216
}
1317

14-
float getLightSpecularCC() {
15-
return calcLightSpecular(ccGlossiness, ccReflDirW);
16-
}
18+
vec3 getLightSpecularCC() {
19+
return calcLightSpecular(ccGlossiness, ccNormalW, vec3(ccSpecularity), ccLightFresnel);
20+
}

0 commit comments

Comments
 (0)