首页 > 代码库 > Unity3D ShaderLab 模拟精灵动画

Unity3D ShaderLab 模拟精灵动画

Unity3D ShaderLab 模拟精灵动画

在上一篇,介绍了通过Shader 模拟纹理运动,那么更深一步讲,我们也可以把帧动画的精灵纹理运动通过shader实现。

虽然大家都是在游戏脚本中做更高一级的控制。但是有钱就是任性,码代码的也可以码任性啊,我们就来试试做精灵的运动动画,遍历播放每一帧。

 

首先呢,准备一个精灵的动画序列帧,没有的找度娘要。然后创建一个新的材质球和新的着色器。然后把准备好的序列帧图拖动到材质的纹理上。

不用多说,_MainTex ("Base (RGB)", 2D) = "white" {},就传递了我们设置好的帧图。

接下来,还要通过Properties来创建动画的数量 速度等。

1add>

Properties {

_MainTex ("Base (RGB)", 2D) = "white" {}

_TexWidht("Image Width",float)=0

_SpriteSize("Sprite Size",float)=0

_Speed("Sprite Speed",Range(0.01,30))=0

}

上面声明的3个对象,同时也要在SubShaderCGPROGRAM下原样申明;

2add>

sampler2D _MainTex;

float _TexWidht;

float _SpriteSize;

float _Speed;

然后我们要把输入的uv值存入独立的变量,保证在代码中的使用。

3add>

void surf (Input IN, inout SurfaceOutput o) {

//uv值存入spriteuv;

float2 spriteUV = IN.uv_MainTex;

//计算单元格的百分比;

float pixeWidth = _TexWidht/_SpriteSize;

float uvPercentage = pixeWidth/_TexWidht;

float timeVal = fmod(_Time.y*_Speed,_SpriteSize);

timeVal = ceil(timeVal);

//计算sprite x方向上的偏移;

float xValue = spriteUV.x;

xValue+=uvPercentage*timeVal*_SpriteSize;

xValue*=uvPercentage;

//刷新uv;

spriteUV = float2(xValue,spriteUV.y);

//传递新的uv;

half4 c = tex2D (_MainTex, spriteUV);

o.Albedo = c.rgb;

o.Alpha = c.a;

}

保存代码,回到编辑器中预览吧。

 技术分享技术分享

通过上面的逻辑实现,我们不难看出我们首先从input结构体中获得到了uv值,把他存入到变量spriteUV 中,这个变量同时包含了uvxy坐标。

接下来,我们获得在gui面板中传入的纹理宽度TexWidht和精灵数量SpriteSize,通过这两个纹理的参数获得了每一个sprite的宽度和每一个spriteuv中所占的比例值,

这个比例值uvPercentage 表示我们的sprite从上一个精灵单元格到下一个精灵单元格的uv偏移量。

最后,我们通过计算时间递增获得了最新的偏移值,在计算过程中用到了fmod()ceil()函数。

最终我们得到了当前的uv值,传递给tex2D()函数,这样我们的sprite就像播放动画一样动起来;

fmod(x,y):返回x/y的余数,符号同xy不可为0

ceil(x):对输入参数向上取整,直到其值等于SpriteSize他就从新归0

上面我们使用了x方向上的uv偏移,同理也可以加入y方向的uv偏移。从而满足更大的精灵表单循环。

 

code start-------------------------------------------------

 

Shader "91YGame/BasicSpriteAni" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
        _TexWidht("Image Width",float)=0
        _SpriteSize("Sprite Size",float)=0
        _Speed("Sprite Speed",Range(0.01,30))=0
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
        
        CGPROGRAM
        #pragma surface surf Lambert

        sampler2D _MainTex;
        float _TexWidht;
        float _SpriteSize;
        float _Speed;

        struct Input {
            float2 uv_MainTex;
        };

        void surf (Input IN, inout SurfaceOutput o) {
            //uv值存入spriteuv;
            float2 spriteUV = IN.uv_MainTex;
            //计算单元格的百分比;
            float pixeWidth = _TexWidht/_SpriteSize;
            float uvPercentage = pixeWidth/_TexWidht;

            float timeVal = fmod(_Time.y*_Speed,_SpriteSize);
            timeVal = ceil(timeVal);
            //计算sprite x方向上的偏移;
            float xValue = http://www.mamicode.com/spriteUV.x;
            xValue+=uvPercentage*timeVal*_SpriteSize;
            xValue*=uvPercentage;
            //刷新uv值;
            spriteUV = float2(xValue,spriteUV.y);
            //传递新的uv值;
            half4 c = tex2D (_MainTex, spriteUV);
            o.Albedo = c.rgb;
            o.Alpha = c.a;
        }
        ENDCG
    }
    FallBack "Diffuse"
}

 

code end---------------------------------------------------

Unity3D ShaderLab 模拟精灵动画