[Question] Confused about the fresnel formula
The origin fresnel schlick is:
This is what Filament do (From brdf.fs)
vec3 F_Schlick(const vec3 f0, float f90, float VoH) {
// Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"
return f0 + (f90 - f0) * pow5(1.0 - VoH);
}
vec3 F_Schlick(const vec3 f0, float VoH) {
float f = pow(1.0 - VoH, 5.0);
return f + f0 * (1.0 - f);
}
float F_Schlick(float f0, float f90, float VoH) {
return f0 + (f90 - f0) * pow5(1.0 - VoH);
}
This is what Babylon.js do (From pbrBRDFFunctions.fx)
vec3 fresnelSchlickGGX(float VdotH, vec3 reflectance0, vec3 reflectance90)
{
return reflectance0 + (reflectance90 - reflectance0) * pow5(1.0 - VdotH);
}
float fresnelSchlickGGX(float VdotH, float reflectance0, float reflectance90)
{
return reflectance0 + (reflectance90 - reflectance0) * pow5(1.0 - VdotH);
}
This is what Three.js do (From bsdfs.glsl.js)
vec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {
// Original approximation by Christophe Schlick '94
// float fresnel = pow( 1.0 - dotLH, 5.0 );
// Optimized variant (presented by Epic at SIGGRAPH '13)
// https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf
float fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );
return ( 1.0 - specularColor ) * fresnel + specularColor;
} // validated
This is what PlayCanvas do (From fresnelSchlick.frag)
void getFresnel() {
float fresnel = 1.0 - max(dot(dNormalW, dViewDirW), 0.0);
float fresnel2 = fresnel * fresnel;
fresnel *= fresnel2 * fresnel2;
fresnel *= dGlossiness * dGlossiness;
dSpecularity = dSpecularity + (1.0 - dSpecularity) * fresnel;
#ifdef CLEARCOAT
// ...
#endif
}
All of them use the half vector when calculating fresnel except playcanvas. The three.js implementation is a little different, and it is migrated from 2013SiggraphPresentationsNotes.
I have the following confusion:
- Why playcanvas use
V dot Ninstead ofV dot H? - What does
dGlossiness * dGlossinessdo here ? Is it used to replacef90 - f0?
@scarletsky - great timing, @raytranuk is just investigating the lighting problems with this specifically ;)
@scarletsky - you observations were correct - the fresnel implementation in PlayCanvas was not using the half-angle and this did result in non-standard specular lighting results that differed significantly from other implementations. A related PR has now been submitted: https://github.com/playcanvas/engine/pull/3172 - which switches the fresnel calculations to use the half-angle and should bring PlayCanvas more in line with other implementations. The use dGlossiness in the fresnel calculation is also non-standard in Cook-Torrance PBR models - but is used a bit like a Geometry term in the Blinn-Phong model that is the default for punctual lights in PlayCanvas.
related to https://github.com/playcanvas/engine/issues/3013
Hey @mvaligursky and @GSterbrant - I'm scanning some older issues to see if any can be closed. What's the current status of this one?
This should have been fixed in #4386.