Sign in to follow this  

Conservation Factor for Epic’s Shading Model

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
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.

Edited by Radikalizm

Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this