shader篇-动画

shader篇-动画


纹理动画

序列帧动画

简介

序列帧动画是最常见的纹理动画之一,像放动画一样播放一系列关键帧图像,相当灵活,不需要物理计算,但美术工作量比较大。

属性配置
Properties {
        _Color ("Color Tint", Color) = (1, 1, 1, 1)

        //关键帧图像纹理
        _MainTex ("Image Sequence", 2D) = "white" {}

        //水平方向关键帧图像个数
        _HorizontalAmount ("Horizontal Amount", Float) = 4
        _VerticalAmount ("Vertical Amount", Float) = 4

        //序列帧动画播放速度
        _Speed ("Speed", Range(1, 100)) = 30
    }
状态配置

帧动画通常包含透明通道,所以被当成半透明对象来设置shader,开启混合模式,关闭深度写入

Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}

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

            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM

            #pragma vertex vert  
            #pragma fragment frag

            #include "UnityCG.cginc"
顶点着色器和输入输出结构体
fixed4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            float _HorizontalAmount;
            float _VerticalAmount;
            float _Speed;

            struct a2v {  
                float4 vertex : POSITION; 
                float2 texcoord : TEXCOORD0;
            };  

            struct v2f {  
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
            };  

            v2f vert (a2v v) {  
                v2f o;  
                o.pos = UnityObjectToClipPos(v.vertex);  
                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);  
                return o;
            }
片元着色器
fixed4 frag (v2f i) : SV_Target {

    //内置变量_Time.y和速度属性相乘得到模拟的时间
    float time = floor(_Time.y * _Speed);
    //计算行列索引
    float row = floor(time / _HorizontalAmount);
    float column = time - row * _HorizontalAmount;

    //构建采样坐标
    //half2 half2 uv = float2(i.uv.x /_HorizontalAmount, i.uv.y / _VerticalAmount);
    half2 uv = i.uv + half2(column, -row);
//  uv.x += column / _HorizontalAmount;
//  uv.y -= row / _VerticalAmount;
    uv.x /=  _HorizontalAmount;
    uv.y /= _VerticalAmount;

    fixed4 c = tex2D(_MainTex, uv);
    c.rgb *= _Color;

    return c;
}
fallback
    FallBack "Transparent/VertexLit"
配置序列帧动画图像

这里写图片描述

滚动的背景

简介

很多2D游戏使用不断滚动的背景模拟游戏角色在场景的穿梭,这种无限滚动的背景也是由纹理动画来实现。

属性配置
Properties {
    //较远的背景纹理
    _MainTex ("Base Layer (RGB)", 2D) = "white" {}
    //较劲的背景纹理
    _DetailTex ("2nd Layer (RGB)", 2D) = "white" {}
    _ScrollX ("Base layer Scroll Speed", Float) = 1.0
    _Scroll2X ("2nd layer Scroll Speed", Float) = 1.0

    //控制纹理整体亮度
    _Multiplier ("Layer Multiplier", Float) = 1
    }
其他配置和顶点着色器
Tags { "RenderType"="Opaque" "Queue"="Geometry"}

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

    CGPROGRAM

    #pragma vertex vert
    #pragma fragment frag

    #include "UnityCG.cginc"

    sampler2D _MainTex;
    sampler2D _DetailTex;
    float4 _MainTex_ST;
    float4 _DetailTex_ST;
    float _ScrollX;
    float _Scroll2X;
    float _Multiplier;

    struct a2v {
        float4 vertex : POSITION;
        float4 texcoord : TEXCOORD0;
    };

    struct v2f {
        float4 pos : SV_POSITION;
        float4 uv : TEXCOORD0;
    };

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

        //利用_Time.y对纹理坐标进行偏移,以达到滚动的效果
        o.uv.xy = TRANSFORM_TEX(v.texcoord, _MainTex) + frac(float2(_ScrollX, 0.0) * _Time.y);
        o.uv.zw = TRANSFORM_TEX(v.texcoord, _DetailTex) + frac(float2(_Scroll2X, 0.0) * _Time.y);

        return o;
    }
片元着色器
fixed4 frag (v2f i) : SV_Target {
    fixed4 firstLayer = tex2D(_MainTex, i.uv.xy);
    fixed4 secondLayer = tex2D(_DetailTex, i.uv.zw);

    fixed4 c = lerp(firstLayer, secondLayer, secondLayer.a);
    c.rgb *= _Multiplier;

    return c;
}
fallback
FallBack "VertexLit"

顶点动画

游戏中所有物体都是静止,顶点动画能让场景更加生动有趣

流动河流

河流的模拟是顶点动画最常见的应用之一。

属性配置
Properties {
//河流纹理
_MainTex ("Main Tex", 2D) = "white" {}

//整体颜色
_Color ("Color Tint", Color) = (1, 1, 1, 1)

//水流波动幅度
_Magnitude ("Distortion Magnitude", Float) = 1

//波动频率
 _Frequency ("Distortion Frequency", Float) = 1

 //波长的倒数
 _InvWaveLength ("Distortion Inverse Wave Length", Float) = 10

 //河流移动速度
 _Speed ("Speed", Float) = 0.5
    }
状态配置和输入输出结构体

“DisableBatching”=”True”防止unity对该shader使用批处理。因为批处理会合并所有相关模型,导致模型失去自己的模型空间
开启了混合模式,关闭了剔除功能,让水流每个面都能显示。

Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "DisableBatching"="True"}

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

            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            Cull Off

            CGPROGRAM  
            #pragma vertex vert 
            #pragma fragment frag

            #include "UnityCG.cginc" 

            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed4 _Color;
            float _Magnitude;
            float _Frequency;
            float _InvWaveLength;
            float _Speed;

            struct a2v {
                float4 vertex : POSITION;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
            }
顶点着色器设置顶点动画
v2f vert(a2v v) {
    v2f o;

    float4 offset;
    offset.yzw = float3(0.0, 0.0, 0.0);

    //利用_Frequency 属性合_Time.y控制住正弦函数的频率
    //模型空间的位置分量乘以_InvWaveLength 来控制波长
    offset.x = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;

    //位置上加入偏移
    o.pos = UnityObjectToClipPos(v.vertex + offset);

    o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
    o.uv +=  float2(0.0, _Time.y * _Speed);

    return o;
}
片元着色器和fallback
fixed4 frag(v2f i) : SV_Target {
                fixed4 c = tex2D(_MainTex, i.uv);
                c.rgb *= _Color.rgb;

                return c;
            } 

            ENDCG
        }
    }
    FallBack "Transparent/VertexLit"
}

广告牌技术

广告牌技术会根据视角方向来旋转一个纹理着色的多边形,使多边形看起来对着摄像机,渲染烟雾,云朵,闪光效果经常用到这个技术。
他的本质是构建旋转矩阵。一个变换矩阵需要3个基向量,广告牌技术的基向量分别是表面法线,指向上的方向,指向右的方向。

属性配置
Properties {
        _MainTex ("Main Tex", 2D) = "white" {}
        _Color ("Color Tint", Color) = (1, 1, 1, 1)

        //约束垂直方向的程度
        _VerticalBillboarding ("Vertical Restraints", Range(0, 1)) = 1 
    }
标签配置

“DisableBatching”=”True”在这里使用因为要保证模型空间的锚点不变

Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "DisableBatching"="True"}

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

            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha
            Cull Off

            CGPROGRAM
顶点着色器
v2f vert (a2v v) {
                v2f o;

                float3 center = float3(0, 0, 0);
                float3 viewer = mul(unity_WorldToObject,float4(_WorldSpaceCameraPos, 1));

                float3 normalDir = viewer - center;

                //向上方向固定为(0,1,0)
                normalDir.y =normalDir.y * _VerticalBillboarding;
                normalDir = normalize(normalDir);

                float3 upDir = abs(normalDir.y) > 0.999 ? float3(0, 0, 1) : float3(0, 1, 0);
                float3 rightDir = normalize(cross(upDir, normalDir));
                upDir = normalize(cross(normalDir, rightDir));

                //计算原生位置相对锚点的偏移
                float3 centerOffs = v.vertex.xyz - center;
                float3 localPos = center + rightDir * centerOffs.x + upDir * centerOffs.y + normalDir * centerOffs.z;

                o.pos = UnityObjectToClipPos(float4(localPos, 1));
                o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);

                return o;
            }
片元着色器和fallback
fixed4 frag (v2f i) : SV_Target {
                fixed4 c = tex2D (_MainTex, i.uv);
                c.rgb *= _Color.rgb;

                return c;
            }

            ENDCG
        }
    } 
    FallBack "Transparent/VertexLit"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值