对表面着色器中的顶点使用动画
我们现在知道了如何访问每个顶点数据的一些基础知识,这次让我们更进一步的了解一些其他类型的数据和顶点的位置。
使用顶点函数,我们可以访问网格中每个顶点位置。具体来说就是可以在着色器处理渲染的过程中,这些函数可以让我们单独对每一个顶点进行修改。
这个知识点当中,我们会创建一个着色器,并且用三角函数的正弦函数( sine wave )来修改网格当中的每一个顶点。该技术可以用来创建旗子飘动或者海浪等物体动画。
始前准备 我们把资源都放一块儿,这样方便我们为顶点着色器( Vertex Shader )编写代码:
- 1.创建一个新的场景,并且创建一个平面网格( plane mesh ),把它放在场景正中央,位置归零。
- 2.然后创建一个新的材质和着色器。
- 3.最后,把着色器挂到材质上,在把材质挂到平面网格上。
最终,你的场景看起来应该跟下图一样:
操作步骤
场景创建好后,鼠标双击打开刚刚我们创建的着色器:- 1.让我们给着色器的属性块下面的预设值:
Properties { _MainTex ("Base (RGB)", 2D) = "white" {} _tintAmount ("Tint Amount", Range(0,1)) = 0.5 _ColorA ("Color A", Color) = (1,1,1,1) _ColorB ("Color B", Color) = (1,1,1,1) _Speed ("Wave Speed", Range(0.1, 80)) = 5 _Frequency ("Wave Frequency", Range(0, 5)) = 2 _Amplitude ("Wave Amplitude", Range(-1, 1)) = 1 }
- 2.接下来我们通过下面的声明告诉Unity,我们需要使用顶点函数了,添加声明的位置在: #pragma statement:
CGPROGRAM #pragma surface surf Lambert vertex:vert
- 3.为了访问属性块中的值,我们还要在 CGPROGRAM 块中声明与之对应的变量:
sampler2D _MainTex; float4 _ColorA; float4 _ColorB; float _tintAmount; float _Speed; float _Frequency; float _Amplitude; float _OffsetVal;
- 4.我们也将使用顶点位置的变化作为 vert 颜色。因为这样我们可以顺便修改物体的颜色了:
struct Input { float2 uv_MainTex; float3 vertColor; }
- 5.此时,我们要修改顶点的表现了,我们要使用到下面的正选函数和顶点函数,在我们的 Input Struct 后面添加如下代码:
void vert(inout appdata_full v, out Input o) { float time = _Time * _Speed; float waveValueA = sin(time + v.vertex.x * _Frequency) * _Amplitude; v.vertex.xyz = float3(v.vertex.x, v.vertex.y + waveValueA, v.vertex.z); v.normal = normalize(float3(v.normal.x + waveValueA, v.normal.y,v.normal.z)); o.vertColor = float3(waveValueA,waveValueA,waveValueA); }
- 6.最后,我们要使用一个 lerp() 函数对两个颜色进行一个插值,这样我们就可以对新网格的波峰和波谷应用不同的颜色,为了获得这种表现,添加下面的代码让顶点函数起作用:
void surf (Input IN, inout SurfaceOutput o) { half4 c = tex2D (_MainTex, IN.uv_MainTex); float3 tintColor = lerp(_ColorA, _ColorB, IN.vertColor).rgb; o.Albedo = c.rgb * (tintColor * _tintAmount); o.Alpha = c.a; }
当你完成了着色器的编写后,回到Unity并且等待着色器编译完成。当编译完成后,你就会看到如下图所示的情形:
原理介绍
这个特定的着色器使用了我们上个知识点的一些概念,但不同的是,我们这里改变的是网格上那些顶点的位置。有时候你不想用骨骼结构( skeleton structure )或者是节点结构( hierarchy of transforms )来扣动画, 然后在简单的拼接它们,比如旗帜,在旗子上做动画然后跟旗杆组合拼接成旗帜。这个时候你使用这个着色器就特别有用了。我们简单的使用了正弦函数 sin() 来创建正弦波,这个函数式Cg语言内建的。当计算好正弦值后,我们把这个值赋值给了每个顶点位置的 y,然后就产生了波动的效果。
当然我们还顺便稍微修改了网格上面的法线,让它针对正弦波有更真实的着色。
从这里你也可以知道,通过利用表面着色器内建的顶点参数,来获得一些比较复杂的顶点效果,还是比较容易的。
希望它能帮到你或者帮你找到思路(^_^)选个表情,或者留个评论吧!