Unity Shader UV动画(序列帧动画)

这一节我们用下面的图片:

来实现动态的熊熊的烈火效果:


我们先来看一下全部的Shader代码,然后再进行分析

Shader "Custom/UVAnim"
{
	Properties
	{
		_Color("Base Color", Color) = (1,1,1,1)
		_MainTex("Base(RGB)", 2D) = "white" {}
	}
	
	SubShader
	{
		tags{"Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True"}
		Blend SrcAlpha OneMinusSrcAlpha
		
		Pass
		{
			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#include "UnityCG.cginc"
			
			float4 _Color;
			sampler2D _MainTex;
			
			struct v2f
			{
				float4 pos:POSITION;
				float2 uv:TEXCOORD0;
			};
			
			float2 moveUV(float2 vertUV)
			{
				float textureNum = 12.0;
				float timePerFrame = 100;
				
				float index = frac(_Time.x / textureNum * timePerFrame);
				float2 uvScale = float2(1 / textureNum, 1);
				
				if(index <= uvScale.x)
					return vertUV * uvScale;
				else if(index <= 2 * uvScale.x)	
					return vertUV * uvScale + float2(uvScale.x, 0.0);
				else if(index <= 3 * uvScale.x)
					return vertUV * uvScale + float2(2 * uvScale.x, 0.0);
				else if(index <= 4 * uvScale.x)	
					return vertUV * uvScale + float2(3 * uvScale.x, 0.0);
				else if(index <= 5 * uvScale.x)
					return vertUV * uvScale + float2(4 * uvScale.x, 0.0);
				else if(index <= 6 * uvScale.x)
					return vertUV * uvScale + float2(5 * uvScale.x, 0.0);
				else if(index <= 7 * uvScale.x)	
					return vertUV * uvScale + float2(6 * uvScale.x, 0.0);
				else if(index <= 8 * uvScale.x)
					return vertUV * uvScale + float2(7 * uvScale.x, 0.0);
				else if(index <= 9 * uvScale.x)	
					return vertUV * uvScale + float2(8 * uvScale.x, 0.0);
				else if(index <= 10 * uvScale.x)
					return vertUV * uvScale + float2(9 * uvScale.x, 0.0);
				else if(index <= 11 * uvScale.x)
					return vertUV * uvScale + float2(10 * uvScale.x, 0.0);
				else
					return vertUV * uvScale + float2(11 * uvScale.x, 0.0);
			}
			
			v2f vert(appdata_base v)
			{
				v2f o;
				o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
				o.uv = moveUV(v.texcoord.xy);
				return o;
			}
			
			half4 frag(v2f i):COLOR
			{	
				half4 c = tex2D(_MainTex , i.uv) * _Color;
				return c;
			}
			
			ENDCG
		}
	}
}

首先属性部分Properties和Tags标签我们前面已经讲过了,然后是混合Blend

Blend SrcAlpha OneMinusSrcAlpha 这句话的意思是拿 源颜色和目标颜色进行混合

关于混合就是:

color = (RGBsrc * Ksrc) OP (RGBdst * Kdst)

其中color表示alpha混合后的颜色值,RGBsrc表示源颜色值,即将要绘制的图元的颜色值;Ksrc表示源混合系数,通常赋值为表示半透明程度的alpha值,用来和RGBsrc相乘。RGBdst表示目标颜色值,即当前颜色缓冲区中的颜色值,Kdst表示目标混合系数,用来和RGBdst相乘。OP表示源计算结果与颜色缓冲区计算结果的混合方法即源计算结果与颜色缓冲区计算结果相加,至于混合的方法OP和混合系数Ksrc和Kdst请参阅unity文档,有很多种。


我们的顶点着色器vert和片段着色器函数frag中的代码很好理解。不好理解的就是我们去uv坐标的moveUV函数。

moveUV函数要求传入一个float2类型的uv值,然后我们定义了两个变量

float textureNum = 12.0;
float timePerFrame = 100;

为什么我们定义textureNum为12,因为我们的图片上有12个小火的形象,我们会分别取他们。

我们来看看我们是怎么来用他们的

 

float index = frac(_Time.x / textureNum * timePerFrame);

关于_Time unity文档中是这样解释的

 

frac函数返回一个数据的小数部分那么_Time.x / textureNum就可以返回1/12-1之间的数值,乘以timePerFrame是控制0-11之间的变换速度的。

也就是我们的index值在0-11之间。

下面这句话很简单,就不解释了。

float2 uvScale = float2(1 / textureNum, 1);

我们来解释这三句,其他的都是一样。

if(index <= uvScale.x)
	return vertUV * uvScale;
else if(index <= 2 * uvScale.x)	
	return vertUV * uvScale + float2(uvScale.x, 0.0);
else if(index <= 3 * uvScale.x)
	return vertUV * uvScale + float2(2 * uvScale.x, 0.0);

如果index小于 1/12时,我们把UV坐标乘以1/12

return vertUV * uvScale;

其实我们取的是纹理图片的第一个火的纹理。

当index小于2/12时,我们把UV坐标乘以1/12再加上float2(uvScale.x, 0.0)

return vertUV * uvScale + float2(uvScale.x, 0.0);

我们先取到第一个火纹理,然后再加1/12取到第二个火纹理.,最后这句话就是获取第二个火的纹理。

当index小于2/12时,我们把UV坐标乘以1/12再加上float2(2 * uvScale.x, 0.0)

return vertUV * uvScale + float2(2 * uvScale.x, 0.0);

我们先取到第一个火纹理,然后再加2/12取到第三个火纹理.,最后这句话就是获取第三个火的纹理。


这样随着时间的流逝我们会显示不同的纹理,然后进行放大(UV坐标乘以一个数,实际上就是把源纹理放大了),就有了动态火的效果。

 


 







  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值