[渲染向]毛发-各向异性高光

unity,选择默认渲染管线

效果图:

 原理:

通过副切线和对半方向(即视线方向+光照方向)进行点乘计算高光,从而代替blinn-Phong中法线和对半方向的点乘

代码:

   Properties
    {
        _MainTex("MainTex", 2D) = "white"{}
        _SpecularTex("_SpecularTex", 2D) = "black"{}
        _exp("Exp", Range(0.0, 20.0)) = 1.0
        _scale("HightLightScale", Range(0.5, 5.0)) = 1.0
        _shiftControl("shiftControl", Range(-1.0, 1.0)) = 0.0
        _SpecularCol("SpecularCol", color) = (1.0, 1.0, 1.0, 1.0)
        
        
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        Cull Off
        
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            
            #include "UnityCG.cginc"

            uniform sampler2D _MainTex;
            uniform sampler2D _SpecularTex;
            uniform float _exp;
            uniform float _scale;
            uniform float _shiftControl;
            uniform float3 _SpecularCol;

            
            struct VertexInput
            {
                float4 vertex : POSITION;
                float4 tangent : TANGENT;
                float4 normal : NORMAL;
                float2 uv : TEXCOORD0;
            };

            struct VertexOutput
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
                float3 posWS : TEXCOORD1;
                float3 nDir : TEXCOORD2;
                float3 tDir : TEXCOORD3;
                float3 bDir : TEXCOORD4;
            };


            VertexOutput vert (VertexInput v)
            {
                VertexOutput o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.posWS = mul(unity_ObjectToWorld, v.vertex);
                o.nDir = UnityObjectToWorldNormal(v.normal);
                o.tDir = UnityObjectToWorldDir(v.tangent.xyz);
                o.bDir = cross(o.tDir, o.nDir);
                o.uv = v.uv;
                return o;
            }

            fixed4 frag (VertexOutput i) : SV_Target
            {
                //mainTex
                float3 var_MainTex = tex2D(_MainTex, i.uv);

                //数据准备
                float3 lDir = _WorldSpaceLightPos0.xyz;
                float3 vDir = _WorldSpaceCameraPos.xyz - i.posWS;
                float3 nDir = i.nDir;
                float3 tDir = i.tDir;
                float3 bDir = i.bDir;
                float3 hDir = normalize(lDir + vDir);

                //偏移bDir
                float var_SpecularTex = tex2D(_SpecularTex, i.uv) - 0.5;  //控制高光以及偏移量
                bDir = normalize(bDir + (var_SpecularTex + _shiftControl) * nDir);   //偏移后的结果
                
                //点积准备
                float ndotl = dot(nDir, lDir);
                float bdoth = dot(bDir, hDir);

                //光照模型
                //half-Lambert
                float diffusion = ndotl * 0.5 + 0.5;

                //Kajiya-Kay
                float sinBH = sqrt(1 - bdoth * bdoth);
                float dirAtten = smoothstep(-1.0, 0.0, bdoth);  //控制衰减
                float3 specular = dirAtten * pow(sinBH, _exp) * 0.3 * _SpecularCol;
                
                //返回最终值
                float finalLight = diffusion + specular;
                float3 finalCol = var_MainTex * diffusion + specular;
                
                return float4(finalCol, 1.0);
            }
            ENDCG
        }
    }

猜你喜欢

转载自blog.csdn.net/TingQiaoQiao/article/details/129904594