N dot L 和 N dot V 要 Max 0, 这里的 k 基于几何函数是针对直接光照还是针对 IBL 光照的重映射 (Remapping) 在 ue 中用的是 [Heitz 2014, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs"]
G
1 2 3 4 5 6 7
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 ); }
float d = ( CosTheta * a2 - CosTheta ) * CosTheta + 1; float D = a2 / ( PI*d*d ); float PDF = D * CosTheta;
returnfloat4( H, PDF ); }
float3 SpecularIBL( uint2 Random, float3 SpecularColor, float Roughness, float3 N, float3 V ) { float3 SpecularLighting = 0;
const uint NumSamples = 32; for( uint i = 0; i < NumSamples; i++ ) { float2 E = Hammersley( i, NumSamples, Random ); float3 H = TangentToWorld( ImportanceSampleGGX( E, Pow4(Roughness) ).xyz, N ); float3 L = 2 * dot( V, H ) * H - V;
float NoV = saturate( dot( N, V ) ); float NoL = saturate( dot( N, L ) ); float NoH = saturate( dot( N, H ) ); float VoH = saturate( dot( V, H ) );