Unity——火燒+水波紋效果(噪音圖)

使用雜訊圖實現火燒和水波紋效果;

1.溶解

關閉裁剪,根據noise紋理取樣,r通道和_BurnAmount比較,裁剪掉小於_BurnAmount的片元;

通過菲尼爾得到裁剪邊緣,添加火焰燃燒的顏色進行混合;

陰影pass需要單獨寫,同樣做裁剪;

image-d129

Pass
{
    Tags {"LightMode" = "ForwardBase"}

    Cull Off

    CGPROGRAM
    #pragma vertex vert
    #pragma fragment frag

    #include "UnityCG.cginc"
    #include "Lighting.cginc"
    #include "AutoLight.cginc"

    #pragma multi_compile_fwdbase

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

    struct v2f
    {
        float4 uv : TEXCOORD0;
        float2 uvBurnMap : TEXCOORD1;
        float4 pos : SV_POSITION;
        float3 lightDir : TEXCOORD2;
        float3 worldPos : TEXCOORD3;
        SHADOW_COORDS(5)
    };

    float _BurnAmount;
    float _LineWidth;
    sampler2D _MainTex;
    float4 _MainTex_ST;
    sampler2D _BumpMap;
    float4 _BumpMap_ST;
    fixed4 _BurnFirstColor;
    fixed4 _BurnSecondColor;
    sampler2D _BurnMap;
    float4 _BurnMap_ST;

    v2f vert (appdata v)
    {
        v2f o;
        o.pos = UnityObjectToClipPos(v.vertex);

        o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
        o.uv.zw = TRANSFORM_TEX(v.uv, _BumpMap);
        o.uvBurnMap = TRANSFORM_TEX(v.uv,_BurnMap);

      	TANGENT_SPACE_ROTATION;
        o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;
        o.worldPos = mul(unity_ObjectToWorld,v.vertex).xyz;
        TRANSFER_SHADOW(o);

        return o;
    }

    fixed4 frag (v2f i) : SV_Target
    {
        fixed3 burn = tex2D(_BurnMap,i.uvBurnMap).rgb;
        clip(burn.r - _BurnAmount);

        float3 tangentLightDir = normalize(i.lightDir);
        fixed3 tangentNormal = UnpackNormal(tex2D(_BumpMap, i.uv.zw));

        fixed3 albedo = tex2D(_MainTex,i.uv.xy).rgb;
        fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

        fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal,tangentLightDir));

        //離裁剪邊緣的距離,在0-邊寬中的百分比,返回0-1中的一個對應值,1-獲得剩餘半段;
        fixed t = 1 - smoothstep(0.0, _LineWidth, burn.r - _BurnAmount);
        //菲尼爾混合顏色
        fixed3 burnColor = lerp(_BurnFirstColor, _BurnSecondColor, t);
        burnColor = pow(burnColor, 5);

        UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);

        //step,_BurnAmount<=0.00001返回1,否則返回0;插值混合顏色,
        fixed3 finalColor = lerp(ambient + diffuse * atten, burnColor, t * step(0.0001,_BurnAmount));
        
        return fixed4(finalColor, 1);
    }
    ENDCG
}

2.水波紋

設置速度來擾動法線法線;擾動的偏移乘以螢幕坐標的z值模擬深度越大折射越大的效果;

GrabPass抓取螢幕畫面做紋理,供折射取樣;

MainTex是一張噪音紋理圖,取樣做速度偏移,模擬水波紋;

fresnel混合折射反射,得到最終顏色;

jluhvfghjkl

fixed4 frag (v2f i) : SV_Target
{
    float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
	fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
	float2 speed = _Time.y * float2(_WaveXSpeed, _WaveYSpeed);

    //速度來擾動法線,速度上下偏移解包法線兩次,取中間
	fixed3 bump1 = UnpackNormal(tex2D(_WaveMap, i.uv.zw + speed)).rgb;
	fixed3 bump2 = UnpackNormal(tex2D(_WaveMap, i.uv.zw - speed)).rgb;
	fixed3 bump = normalize(bump1 + bump2);

    //根據法線計算偏移
    float2 offset = bump.xy * _Distortion * _RefractionTex_TexelSize.xy;
    
    //乘以z模擬深度越大折射程度越大
	i.scrPos.xy = offset * i.scrPos.z + i.scrPos.xy;
    
    //透視除法取折射紋素
	fixed3 refrCol = tex2D( _RefractionTex, i.scrPos.xy/i.scrPos.w).rgb;

    //求世界空間法線
	bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));
   
    //主紋理動畫,模擬水波紋
	fixed4 texColor = tex2D(_MainTex, i.uv.xy + speed);
    
    //計算反射混合主紋理顏色
	fixed3 reflDir = reflect(-viewDir, bump);
	fixed3 reflCol = texCUBE(_Cubemap, reflDir).rgb * texColor.rgb * _Color.rgb;

    //fresnel混合反射和折射
    fixed fresnel = pow(1 - saturate(dot(viewDir,bump)),4);
    fixed3 finalColor = reflCol * fresnel + refrCol *(1-fresnel);

    return fixed4(finalColor,1.0); 
}

此外,噪音圖還用在全局霧和生成地形,以及動態生成資源上;

Tags: