XDRender_LightMode_Anisotropic(2) 各项异性着色(2) 切线
一、为何是切线
还是这个图, 需要更深的理解.
为何需要切线来做?
其实我们去看一个图和一个算法能更清楚, 这里就需要说明什么叫各项异性的异性来源. 可以理解为当不同的观察角度,会有不同的影响因子. (有点薛定谔了 哈哈).
观察角度
这里观察角度就是ViewDir
影响因子
得出的影响因子,其实还是法线. 这是这时候的法线由于我们的观察角度被改变了.
其实这样做的原因,还是由于精度和性能, 可以详细非常细非常细的丝线, 环绕的法线就有一圈. 这时候我们不可能完全物理来计算. 所以做了一个近似. 只需要有个切线(变化了一丢丢的)加上观察角度. 就能算出一个大概.
下面是一个还不够细的线, 想象我们再进入微观一点.
细看这个不完全符合物理的
float Aniso_StrandSpecular(float3 T, float3 V, float L, float exponent)
{
float3 H = normalize(L + V);
float dotTH = dot(T, H);
float sinTH = sqrt(1.0 - dotTH*dotTH);
float dirAtten = smoothstep(-1.0, 0.0, dot(T, H));
return dirAtten * pow(sinTH, exponent);
}
二、切线、法线到切线, 切线和方向影响到法线
1、法线到切线的一种步骤
法线纹理
在切线空间
法线
根据计算出的切线空间的法线,经过空间转换,得到世界空间
切线
这时候(世界空间下)根据法线和副切线 得到切线
(世界空间)扰动了切线
法线加重对切线的影响
inputData.tangentWS = ShiftTangent(tangentWS,input.normalWS,_CustomData.z);
影响计算
几种经验:
dot(N,H)^specularity
其中切线方向可以用外部纹理等给到
fixed HdotA = dot(normalize(Normal + AnisoDirection), halfVector);
float aniso = max(0, sin(radians((HdotA + _AnisoOffset) * 180f)));
float spec = saturate(pow(aniso, Gloss * 128) );
sin(T,H)^specularity
1、Kajiya-Kay
![image-20201120171519068](file:///Users/wumingfei/Documents/OneDriver/OneDrive%20-%20sensetime/DaoZhangOneNote/MYBlobTemp/Render/XDGameEngine/XDGameEngine_Unity/Pass_Light/XDRender_LightMode_Anisotropic2.assets/image-20201120171519068.png?lastModify=1605864195)
2、 circle各向异性, 对Kajiya-Kay一种近似
ward各向异性
这里主要是有粗糙度对两个方向的影响
第一张
ward各向异性分布函数的优点是可以使用comb贴图,也就是各向异性方向贴图,有作为tangent方向矫正各向异性高光形状及方向的功能
if (dotLN < 0.0) // light source on the wrong side?
{
specularReflection = vec3(0.0, 0.0, 0.0);
// no specular reflection
}
else // light source on the right side
{
float dotHN = dot(halfwayVector, normalDirection);
float dotVN = dot(viewDirection, normalDirection);
float dotHTAlphaX =
dot(halfwayVector, tangentDirection) / _AlphaX;
float dotHBAlphaY = dot(halfwayVector,
binormalDirection) / _AlphaY;
specularReflection = attenuation * vec3(_SpecColor)
* sqrt(max(0.0, dotLN / dotVN))
* exp(-2.0 * (dotHTAlphaX * dotHTAlphaX
+ dotHBAlphaY * dotHBAlphaY) / (1.0 + dotHN));
}
}
迪斯尼的G和D两项
// specular
float aspect = sqrt(1-anisotropic*.9);
float ax = max(.001, sqr(roughness)/aspect);
float ay = max(.001, sqr(roughness)*aspect);
float D_GTR2_aniso(float dotHX, float dotHY, float dotNH, float ax, float ay)
{
float deno = dotHX * dotHX / (ax * ax) + dotHY * dotHY / (ay * ay) + dotNH * dotNH;
return 1.0 / (PI * ax * ay * deno * deno);
}
/ Smith GGX G项,各项异性版本
// Derived G function for GGX
float smithG_GGX_aniso(float dotVN, float dotVX, float dotVY, float ax, float ay)
{
return 1.0 / (dotVN + sqrt(pow(dotVX * ax, 2.0) + pow(dotVY * ay, 2.0) + pow(dotVN, 2.0)));