XDRender_LightMode_Anisotropic(2) 各项异性着色(2) 切线

时间:2020-11-21
本文章向大家介绍XDRender_LightMode_Anisotropic(2) 各项异性着色(2) 切线,主要包括XDRender_LightMode_Anisotropic(2) 各项异性着色(2) 切线使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

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)));