方便自己看看ShadingModels.ush
float3 SpecularGGX( float Roughness, float3 SpecularColor, BxDFContext Context, float NoL, FAreaLight AreaLight )
{
float a2 = Pow4( Roughness );
float Energy = EnergyNormalization( a2, Context.VoH, AreaLight );
// Generalized microfacet specular
float D = D_GGX( a2, Context.NoH ) * Energy;
float Vis = Vis_SmithJointApprox( a2, Context.NoV, NoL );
float3 F = F_Schlick( SpecularColor, Context.VoH );
return (D * Vis) * F;
}
float EnergyNormalization( inout float a2, float VoH, FAreaLight AreaLight )
{
if( AreaLight.SphereSinAlphaSoft > 0 )
{
// Modify Roughness
a2 = saturate( a2 + Pow2( AreaLight.SphereSinAlphaSoft ) / ( VoH * 3.6 + 0.4 ) );
}
float Sphere_a2 = a2;
float Energy = 1;
if( AreaLight.SphereSinAlpha > 0 )
{
Sphere_a2 = New_a2( a2, AreaLight.SphereSinAlpha, VoH );
Energy = a2 / Sphere_a2;
}
if( AreaLight.LineCosSubtended < 1 )
{
#if 1
float LineCosTwoAlpha = AreaLight.LineCosSubtended;
float LineTanAlpha = sqrt( ( 1.0001 - LineCosTwoAlpha ) / ( 1 + LineCosTwoAlpha ) );
float Line_a2 = New_a2( Sphere_a2, LineTanAlpha, VoH );
Energy *= sqrt( Sphere_a2 / Line_a2 );
#else
float LineCosTwoAlpha = AreaLight.LineCosSubtended;
float LineSinAlpha = sqrt( 0.5 - 0.5 * LineCosTwoAlpha );
float Line_a2 = New_a2( Sphere_a2, LineSinAlpha, VoH );
Energy *= Sphere_a2 / Line_a2;
#endif
}
return Energy;
}
// GGX / Trowbridge-Reitz
// [Walter et al. 2007, "Microfacet models for refraction through rough surfaces"]
float D_GGX( float a2, float NoH )
{
float d = ( NoH * a2 - NoH ) * NoH + 1; // 2 mad
return a2 / ( PI*d*d ); // 4 mul, 1 rcp
}
// Appoximation of joint Smith term for GGX
// [Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"]
float Vis_SmithJointApprox( float a2, float NoV, float NoL )
{
float a = sqrt(a2);
float Vis_SmithV = NoL * ( NoV * ( 1 - a ) + a );
float Vis_SmithL = NoV * ( NoL * ( 1 - a ) + a );
return 0.5 * rcp( Vis_SmithV + Vis_SmithL );
}
// [Schlick 1994, "An Inexpensive BRDF Model for Physically-Based Rendering"]
float3 F_Schlick( float3 SpecularColor, float VoH )
{
float Fc = Pow5( 1 - VoH ); // 1 sub, 3 mul
//return Fc + (1 - Fc) * SpecularColor; // 1 add, 3 mad
// Anything less than 2% is physically impossible and is instead considered to be shadowing
return saturate( 50.0 * SpecularColor.g ) * Fc + (1 - Fc) * SpecularColor;
}