UE毛发系统底层剖析
本文未经允许禁止转载
作者:Heskey0
B站:https://space.bilibili.com/455965619
邮箱:3495759699@qq.com
Unreal Engine - Hair Shading Model
Papers
unreal-engine-hair-and-fur-whitepaper
SIGGRAPH 2016 Course: Physically Based Shading in Theory and Practice
一. Fur Structure
outer --> inner
-
cuticle
-
cortex : absorbs light
-
medulla : scatters light
paths:
- R
- TT
- TRT
notation p represent R, TT or TRT
二. Radiance
curve irradiance : power per unit length
curve intensity : intensity per unit length
bidirectional scattering function :
the most prominent feature in the scattering function is the specular highlight that occurs approximately when $ \theta_r =-\theta_i $
BCSDF : bidirectional curve scattering distribution function
三. Basic concept
normal plane : 垂直于虚拟法线的平面
incidence plane : 由入射光线与入射点处的法线所构成的平面被称为入射面
\(\theta_i,\theta_r\) : inclinations with respect to the normal plane
\(\theta_d=\frac{\theta_i+\theta_r}{2}\) : the difference angle
\(\theta_h=\theta_i+\theta_r\)
\(\phi_i,\phi_r\) : azimuth
\(\phi=\phi_r-\phi_i\)
四. Theory
because of the symmetry of a cylinder, the 4D scattering function can be factored into a product of two 2D terms.
One term, capture the \(\theta\) dependence, called \(M\) : longitudinal scattering function , 纵向的散射方向
One term, capture the \(\phi\) dependence, called \(N\) : azimuthal scattering function , 头发横截面的散射方向
for M, 符合高斯函数 :
[EGSR2011 An Energy-Conserving Hair Reflectance Model] 4.1
where g is a normalized Gaussian of longitudinal inclination \(\theta\), \(\beta\) is a roughness term
for N, 可做一些简化 :
1. R
[EGSR2011 An Energy-Conserving Hair Reflectance Model] 4.1
where A : Attenuation term
where F : Schlick Fresnel
other paths too complex and minor impact
2. TT
[A Data-Driven Light Scattering Model for Hair] 3.2
where A : Attenuation term
where T : Absorption term
and
float f = Hair_F( CosThetaD * sqrt( saturate( 1 - h*h ) ) );
float Fp = Pow2(1 - f);
float Tp = exp(-AbsorptionColor * 2 * abs(1 - Pow2(h * a) / CosThetaD));
we only need to evaluate h, D, T
由于复杂性,需要做一些简化:
2.1 D :
approximation :
float Np = exp( -3.65 * CosPhi - 3.98 );
2.2 eta :
approximation :
error < 0.68%
2.3 h :
approximation :
float h = CosHalfPhi * ( 1 + a * ( 0.6 - 0.8 * CosPhi ) );
2.4 T :
approximation :
3. TRT
h, the offset for Fresnel :
absorption term :
Distribution :
But it’s still missing something ! We need to render a volume of hair not just a single strand
4. Multiple scattering
五. Implementation
file : HairBsdf.ush
function : HairShading()
【notice : HairShadingRef() is a Reference, 由宏REFERENCE控制是否开启,默认是关闭。
HairShading()是HairShadingRef()的近似估计, Lots of curve fitting and function aproximation】
Coding
//R
S += Mp * Np * Fp * (GBuffer.Specular * 2) * lerp(1, Backlit, saturate(-VoL));
//TT
S += Mp * Np * Fp * Tp * Backlit;
//TRT
S += Mp * Np * Fp * Tp;
//Multiple Scattering
float3 EvaluateHairMultipleScattering(
const FHairTransmittanceData TransmittanceData,
const float Roughness,
const float3 Fs)
{
return TransmittanceData.GlobalScattering * (Fs + TransmittanceData.LocalScattering) * TransmittanceData.OpaqueVisibility;
}
S = EvaluateHairMultipleScattering(HairTransmittance, ClampedRoughness, S);
S += KajiyaKayDiffuseAttenuation(GBuffer, L, V, N, Shadow);
(Np * Fp) represent N : azimuthal scattering function
for M
//R
float Mp = Hair_g(B[0] * BScale, SinThetaL + SinThetaV - Shift);
//TT
float Mp = Hair_g( B[1], SinThetaL + SinThetaV - Alpha[1] );
//TRT
float Mp = Hair_g( B[2], SinThetaL + SinThetaV - Alpha[2] );
for N = (Np * Fp)
//R
float Np = 0.25 * CosHalfPhi;
float Fp = Hair_F(sqrt(saturate(0.5 + 0.5 * VoL)));
//TT
float Np = exp( -3.65 * CosPhi - 3.98 );
float h = CosHalfPhi * ( 1 + a * ( 0.6 - 0.8 * CosPhi ) );
float f = Hair_F( CosThetaD * sqrt( saturate( 1 - h*h ) ) );
float Fp = Pow2(1 - f);
//TRT
float Np = exp( 17 * CosPhi - 16.78 );
float f = Hair_F( CosThetaD * 0.5 );
float Fp = Pow2(1 - f) * f;
where
float Hair_g(float B, float Theta)
{
return exp(-0.5 * Pow2(Theta) / (B * B)) / (sqrt(2 * PI) * B);
}
Parameters
- BaseColor
- C in the equation
- Specular
- Scales the R term
- Roughness
- \(\beta_R=Roughness^2\)
- \(\beta_{TT}=0.5Roughness^2\)
- \(\beta_{TRT}=2Roughness^2\)
- Scatter
- Scales multiple scattering term
- Shift
- \(\alpha_R=-2Shift\)
- \(\alpha_{TT}=Shift\)
- \(\alpha_{TRT}=4Shift\)