Unity Shaders and Effects Cookbook (7-2) Surface Shader 中实现 顶点动画

Posted _Captain

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity Shaders and Effects Cookbook (7-2) Surface Shader 中实现 顶点动画相关的知识,希望对你有一定的参考价值。

上一节中说了,在 Surface Shader 中,添加顶点函数,我们可以在 顶点函数中获取到 顶点数据,比如顶点颜色、顶点坐标等。

这一节学习获取顶点坐标,并且修改顶点坐标,来实现顶点动画。


简单介绍原理:

在顶点函数中,获取到顶点坐标 vertex,然后,求float offsetY = sin(vertex.x) ,然后将 offsetY 加到 vertex.y 上,这样就把原来的平面 ,变成了 正弦 波浪。


然后再使用之前学过的 内置变量 _Time ,算式变为 float offsetY=sin(vertex.x * _Time) ,这样就形成了动画。


下面开始练习。

新建Scene,导入随书资源,新建Material、新建Shader。

将新建的 Material 赋值给 Plane 。

刚搭建好场景,如下


按照上面所说的原理,来修改Shader。


1、首先声明参数 vertex ,告诉Unity 我们的Shader 中有顶点函数

pragma surface surf Lambert vertex:vert

2、创建 vert 顶点函数

void vert(inout appdata_full v,out Input o)

	UNITY_INITIALIZE_OUTPUT(Input,o);
	float offsetY=sin(v.vertex.x);

	v.vertex.xyz=float3(v.vertex.x,v.vertex.y+offsetY,v.vertex.z);

在顶点函数中,以 顶点坐标 vertex.x 为参数 ,求sin值 作为 offsetY,然后 vertex.y 与 offsetY 相加。

得到如下图的效果

转自http://blog.csdn.net/huutu  http://www.thisisgame.com.cn

3、使用 _Time ,动起来

void vert(inout appdata_full v,out Input o)

	UNITY_INITIALIZE_OUTPUT(Input,o);
	float offsetY=sin(v.vertex.x + _Time.y);

	v.vertex.xyz=float3(v.vertex.x,v.vertex.y+offsetY,v.vertex.z);



动起来了,但是却没有明暗效果。

这是因为虽然修改了顶点的位置,但是法线数据没有修改。所以现在的法线数据仍然是之前 平面 的那一套。因为平面的法线数据都是相同的,也就没有了明暗之分。


4、修改法线

在顶点函数中修改法线

void vert(inout appdata_full v,out Input o)

	UNITY_INITIALIZE_OUTPUT(Input,o);
	float offsetY=sin(v.vertex.x + _Time.y);

	v.vertex.xyz=float3(v.vertex.x,v.vertex.y+offsetY,v.vertex.z);
	v.normal=normalize(float3(v.normal.x+offsetY,v.normal.y,v.normal.z));



5、看起来更圆滑些

上面的效果中,能很明显的看出 折线,看起来不圆滑。这是因为 Plane 的顶点数不多,比如 x 轴上只有 10个 顶点,这 10个顶点被分配到了 2 个正弦波周期,肯定会看起来曲折。

那么我们减少 正弦波周期,让它看起来更圆滑些。


修改顶点函数中的 sin 这一句

float offsetY=sin(v.vertex.x * 0.5 + _Time.y);


完整Shader 代码

Shader "CookBookShaders/Chapt7-2/VertexAnimation" 

	Properties
	
		_MainTex ("Base (RGB)", 2D) = "white" 
	

	SubShader 
	
		Tags  "RenderType"="Opaque" 
		LOD 200
		
		CGPROGRAM
		#pragma surface surf Lambert vertex:vert

		sampler2D _MainTex;

		struct Input 
		
			float2 uv_MainTex;
		;

		void vert(inout appdata_full v,out Input o)
		
			UNITY_INITIALIZE_OUTPUT(Input,o);
			float offsetY=sin(v.vertex.x * 0.5 + _Time.y);

			v.vertex.xyz=float3(v.vertex.x,v.vertex.y+offsetY,v.vertex.z);
			v.normal=normalize(float3(v.normal.x+offsetY,v.normal.y,v.normal.z));
		

		void surf (Input IN, inout SurfaceOutput o) 
		
			half4 c = tex2D (_MainTex, IN.uv_MainTex);
			o.Albedo = c.rgb;
			o.Alpha = c.a;
		
		ENDCG
	 
	FallBack "Diffuse"


书上还加上了 颜色混合 让效果看起来更炫丽,这里就不做了。

转自http://blog.csdn.net/huutu  http://www.thisisgame.com.cn

了解一下书上提到的一个函数 lerp

Lerp (from : float, to : float, t : float) 

Lerp 插值函数

float f = Lerp(from,to,t)  =  from*(1-t) + to*t


当t = 0返回from,当t = 1 返回to。当t = 0.5 返回from和to的平均值。


示例项目下载

http://pan.baidu.com/s/1qXUbsUK





以上是关于Unity Shaders and Effects Cookbook (7-2) Surface Shader 中实现 顶点动画的主要内容,如果未能解决你的问题,请参考以下文章

Unity Shaders and Effects Cookbook (6-2) 透明裁剪着色器

Unity Shaders and Effects Cookbook (6-1) 使用 alpha 参数的 半透明着色器

Unity Shaders and Effects Cookbook (6-3) 修改渲染队列Queue 来 修改渲染顺序

Unity Shaders and Effects Cookbook (7-3) 在地形中使用顶点颜色做混合

Unity Shaders and Effects Cookbook (D-2) Cull Back背面剔除 -- 模型半边不可见

Unity Shaders and Effects Cookbook (5-1)LitSphere lighting model