# Conservation Factor for Epic’s Shading Model

This topic is 1427 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

What is the conservation factor between the specular and diffuse in Epic’s shading model?
Both they and Disney are ignoring it.
Since it uses typical Fresnel, I am assuming it is:
saturate( (1.0 - SchlickFresnel( _dlaArgs.fSpecReflectance, _dlaArgs.fLdotN )) )

My code is:
// _fCosThetaH = N*H.
// _fW = Roughness^2.
float TrowbridgeReitzD( float _fCosThetaH, float _fW ) {
float fA2 = Sqr( _fW );
return fA2 / (PI * Sqr( Sqr( _fCosThetaH ) * (fA2 - 1.0) + 1.0 ));
}

float SmithG1_GGX( float _fVdotN, float _fAlphaG ) {
return _fVdotN / (_fVdotN * (1.0 - _fAlphaG) + _fAlphaG);
}

// _fAlphaG = Roughness.
float SmithG_GGX( float _fLdotN, float _fVdotN, float _fAlphaG ) {
float fK = Sqr( _fAlphaG + 1.0 ) * (1.0 / 8.0);
return SmithG1_GGX( _fLdotN, fK ) * SmithG1_GGX( _fVdotN, fK );
}

float SchlickFresnel_SG( float _F0, float _fU ) {
return _F0 + (1.0 - _F0) * exp2( (_fU * -5.55473 - 6.98316) * _fU );
}

float EpicShadingSpecular( in DEF_LIGHT_ARGS _dlaArgs, out vec4 _vSpecular ) {
float fD = TrowbridgeReitzD( _dlaArgs.fNdotH, _dlaArgs.fRoughness * _dlaArgs.fRoughness );
float fG = SmithG_GGX( _dlaArgs.fLdotN, _dlaArgs.fVdotN, _dlaArgs.fRoughness );
float fF = SchlickFresnel_SG( _dlaArgs.fSpecReflectance, _dlaArgs.fVdotH );

float fS = fD * fG * fF;
_vSpecular = _dlaArgs.fLdotN * fS * _dlaArgs.vLightDiffuse;

// Returns the specular/diffuse conservation factor.
return saturate( (1.0 - SchlickFresnel_SG( _dlaArgs.fSpecReflectance, _dlaArgs.fLdotN )) );
}

Is it correct to use just the Fresnel (from the light’s point of view, hence L•N, not V•N) or should it include the distribution/geometric terms as well? I tend to think these are typically ignored for performance, but for the moment I am more interested in accuracy.

L. Spiro

##### Share on other sites

Is it correct to use just the Fresnel (from the light’s point of view, hence L•N, not V•N) or should it include the distribution/geometric terms as well? I tend to think these are typically ignored for performance, but for the moment I am more interested in accuracy.

As far as I understand it the diffuse term should indeed take surface roughness into account in some way. Applying the 1.0 - F trick is to account for the trade-off between diffuse and specular at glancing viewing angles, but is not a completely accurate approach.

Naty Hoffman has provided some references for this stuff in her "Physics and Math of Shading" SIGGRAPH course notes: http://blog.selfshadow.com/publications/s2013-shading-course/hoffman/s2013_pbs_physics_math_notes.pdf

Have a look at the bottom of page 20.

EDIT:

It's also always possible to just have a look at the shader code provided in UE4. I have the source lying around here somewhere, but haven't looked into their shaders too much yet.

1. 1
Rutin
31
2. 2
3. 3
4. 4
5. 5

• 13
• 40
• 11
• 10
• 14
• ### Forum Statistics

• Total Topics
632963
• Total Posts
3009534
• ### Who's Online (See full list)

There are no registered users currently online

×