概念

各项同性材质渲染可以认为是在所有方向上均匀地散射光,可以认为一个点的法线N是固定的,而各项异性材质的渲染,在微观上是有各种颗粒和划痕的,一个表面上的点可能有多个法线,所以我们不能用普通的高光模型去计算各向异性的高光


Kajiya-Kay Model原理

依据Blin-Phong 光照模型 高光的强度是通过 pow(max(0, NdotH), _SpecularPow) 计算的,但是各项异性中N没法直接获取,我们需要通过切线T和方向和入射光方向来确定该平面上的法线

在数值上,我们会发现TH的夹角正弦会等于HN的夹角余弦值,得到如下代码

fixed dotTH = dot(tangent, halfDir);
fixed sinTH = sqrt(1.0 - dotTH * dotTH);
//衰减值,dotTH大于0不衰减,dotTH小于0衰减
fixed dirAtten = smoothstep(-1.0, 0.0, dotTH);
fixed kkSpecular = dirAtten * pow(sinTH, _SpecularPowH) * _SpecularAttenL;
fixed3 specular = _SpecularColor.rgb * kkSpecular;

优化

根据以上代码得到效果如下

法线高光是块状的和现实效果不符合

偏移贴图

我们通过Shift Tangent Map对切向方向进行偏移

float shiftTex = tex2D(_SpecularShift, i.uv) - 0.5;
fixed3 tangent = normalize(i.tangent + worldNormal * (_Shift + shiftTex));

得到如下效果

主副光和AO

为了让高光的明暗度更加符合现实,可以通过两层高光来控制高光,并把高光与AO以及阴影进行关联,让高光效果的可调性和敏感变化更好

fixed kkSpecular = dirAtten * (pow(sinTH, _SpecularPowH) * _SpecularAttenL + pow(sinTH, _SpecularPowL) * _SpecularAttenH);
fixed3 specular = _SpecularColor.rgb * kkSpecular * shadowAtten * ao;

模型UV

进行上述优化后,发现高光的纹路线条是扭曲的,并不是很自然

需要对贴图的切线进行修正来提升效果,或者在制作头发贴图时,所有的头发模型的UV都是在垂直方向展开的,这样高光的效果会更好