ShadowGun 旗子飄揚效果shader註解

先看效果:

飄動全是使用shader偏移頂點

的位置做的

幾個點:

1、頂點數據的alpha值,標識了受風的權重。alpha越大,受風越厲害。

通過觀察模型可以看出這點。而shader裏這句也有說明。

以_Time作爲參數,使用frac來取模,形成週期性的動畫。

下面是註釋後的shader

// - Unlit
// - Per-vertex (virtual) camera space specular light
// - SUPPORTS lightmap

Shader "MADFINGER/Environment/Lightmap + Wind" {
Properties {
    _MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
    _Wind("Wind params",Vector) = (1,1,1,1)
    _WindEdgeFlutter("Wind edge fultter factor", float) = 0.5
    _WindEdgeFlutterFreqScale("Wind edge fultter freq scale",float) = 0.5
}

SubShader {
    Tags {"Queue"="Transparent" "RenderType"="Transparent" "LightMode"="ForwardBase"}
    LOD 100
    
    Blend SrcAlpha OneMinusSrcAlpha
    Cull Off ZWrite Off
    
    
    CGINCLUDE
    #include "UnityCG.cginc"
    #include "TerrainEngine.cginc"
    sampler2D _MainTex;
    float4 _MainTex_ST;
    samplerCUBE _ReflTex;
    
    #ifndef LIGHTMAP_OFF        //lightmap是否開啓。如果沒有關閉lightmap。就給lightmap支持下。
    float4 unity_LightmapST;
    sampler2D unity_Lightmap;
    #endif
    
    float _WindEdgeFlutter;            //風導致旗幟震動的振幅
    float _WindEdgeFlutterFreqScale;  //風的時間流逝速度,影響頻率,控制旗子反覆擺動的週期

    struct v2f {
        float4 pos : SV_POSITION;
        float2 uv : TEXCOORD0;
        #ifndef LIGHTMAP_OFF        //開啓lightmap的時候,要使用
        float2 lmap : TEXCOORD1;
        #endif
        fixed3 spec : TEXCOORD2;
    };

inline float4 AnimateVertex2(float4 pos, float3 normal, float4 animParams,float4 wind,float2 time)
{    
    // animParams stored in color
    // animParams.x = branch phase
    // animParams.y = edge flutter factor
    // animParams.z = primary factor
    // animParams.w = secondary factor

    float fDetailAmp = 0.1f;
    float fBranchAmp = 0.3f;
    
    // Phases (object, vertex, branch)
    float fObjPhase = dot(_Object2World[3].xyz, 1);  //這一行直接寫1也行,_Object2World[3],一般情況下應該是0,0,0,1
    float fBranchPhase = fObjPhase + animParams.x;   //由於animParams.x是0,這個也是1
    
    float fVtxPhase = dot(pos.xyz, animParams.y + fBranchPhase);  //根據x,y,z,和振幅+1點乘。離遠點越遠,這個值越大。受振幅影響
    
    // x is used for edges; y is used for branches
    float2 vWavesIn = time  + float2(fVtxPhase, fBranchPhase );  //vWavesIn第一項是點的相位*時間流逝率,第二項就是時間+1.
    
    // 1.975, 0.793, 0.375, 0.193 are good frequencies
    float4 vWaves = (frac( vWavesIn.xxyy * float4(1.975, 0.793, 0.375, 0.193) ) * 2.0 - 1.0); // 將結果乘以頻率,對一取模,然後乘以2,再減一
    
    vWaves = SmoothTriangleWave( vWaves );   //一個優化的正弦波計算。
    float2 vWavesSum = vWaves.xz + vWaves.yw; //振幅疊加,以免太正弦了。

    // Edge (xz) and branch bending (y)
    float3 bend = animParams.y * fDetailAmp * normal.xyz; //沿法線方向根據振幅和參數縮放一個值
    bend.y = animParams.w * fBranchAmp;                      //y根據受風能力,乘以一個參數
    pos.xyz += ((vWavesSum.xyx * bend) + (wind.xyz * vWavesSum.y * animParams.w)) * wind.w;  //再次根據受風能力進行影響。

    // Primary bending
    // Displace position
    pos.xyz += animParams.z * wind.xyz;  //根據受風能力,再次擴大。
    
    return pos;
}


    
    v2f vert (appdata_full v)
    {
        v2f o;
        
        float4    wind;
        
        float            bendingFact    = v.color.a;
        
        wind.xyz    = mul((float3x3)_World2Object,_Wind.xyz);      //風的方向轉爲物體座標。wind參數的xyz表示風的世界座標的方向。_Wind爲風的個方向強度
        wind.w        = _Wind.w  * bendingFact;                        //每個頂點的顏色的alpha值表示此點受風變化的強度。旗子底部這個值較大。wind參數的w表示風力
        
        
        float4    windParams    = float4(0,_WindEdgeFlutter,bendingFact.xx);  //0,旗子振幅,每個頂點的受風強度值
        float         windTime         = _Time.y * float2(_WindEdgeFlutterFreqScale,1);  //風的時間流逝速度
        float4    mdlPos            = AnimateVertex2(v.vertex,v.normal,windParams,wind,windTime); //計算受風之後的位置
        
        o.pos = mul(UNITY_MATRIX_MVP,mdlPos);
        o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
        
        o.spec = v.color;
        
        #ifndef LIGHTMAP_OFF
        o.lmap = v.texcoord1.xy * unity_LightmapST.xy + unity_LightmapST.zw;
        #endif
        
        return o;
    }
    ENDCG


    Pass {
        CGPROGRAM
        #pragma debug
        #pragma vertex vert
        #pragma fragment frag
        #pragma fragmentoption ARB_precision_hint_fastest        //片元着色器選擇低精度的計算方式。5.0以後拋棄掉 fragmentoption的聲明。
        fixed4 frag (v2f i) : COLOR
        {
            fixed4 tex = tex2D (_MainTex, i.uv);
            
            fixed4 c;
            c.rgb = tex.rgb;
            c.a = tex.a;
            
            #ifndef LIGHTMAP_OFF
            fixed3 lm = DecodeLightmap (tex2D(unity_Lightmap, i.lmap));
            c.rgb *= lm;
            #endif
            
            return c;
        }
        ENDCG 
    }    
}
}


中間多次根據風力進行修正的地方,作者寫的蠻複雜,不寫那麼複雜,效果看起來也還行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章