本文主要是介绍UnityShader顶点动画实现Mage-Fiers漂移效果,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
我们需要实现一个模型上所有顶点都随机漂移的效果。开始的时候用的Mage-fiers实现的,需要加载对应的脚本库。感觉代码累赘,所以这里用shader实现了一个相应的效果。静态图如下:
这张效果图有两部分组成,由带有色彩的底图(百度所得)和上面的不规则模型组成,我们要做的就是通过shader使模型顶点漂移起来,让我们开始吧。
//声明一个shader,这个shader为着顶点光照,因为我们只需要看到模型的透明轮廓,不需要进行细腻的着片元计算
//同时这个效果的轮廓受光照的方向影响。
Shader "Demon/SwingAni" {
//属性定义就不解释了
Properties {
_Diffuse("漫反射颜色", Color) = (1.0, 1.0, 1.0, 1.0)
_Speed("动画速度(xyz)和Z方向振幅(w)", Vector) = (1.0, 1.0, 1.0, 1.0)
}
SubShader {
//这是一个透明的shader,所以Queue和RenderType都是Transparent,不会受到投影器影响所以Ignore掉。
//这个shader有顶点动画,所以关闭Unity的Batching功能,不关闭动画效果可能受到影响。
Tags { "Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True" "DisableBatching" = "True"}
Pass {
Tags{"LightMode" = "ForwardBase" }
//根据透明度_Diffuse.a进行混合,下面等于(源颜色*a)+(目标颜色即缓冲区*(1-a))
Blend SrcAlpha OneMinusSrcAlpha
//只渲染正面,在OpenGL中为顶点按逆时针光栅化图元的面,DX相反。
Cull Back
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
//这里系统用POSITION语义填充模型空间的顶点信息
float4 vertex : POSITION;
//这里系统用NORMAL语义填充模型空间的法线信息
float3 normal : NORMAL;
};
struct v2f {
//这里存储了顶点处理之后裁剪空间的坐标信息,是shader中必须计算的。指的是System Value Position
float4 pos : SV_POSITION;
//这里存储了着顶点光照的插值颜色
float4 color : TEXCOORD0;
};
//属性对应的变量声明,只有声明之后属性才能用
fixed4 _Diffuse;
float4 _Speed;
//着顶点计算,这里的漂移算法是根据时间的正玄波移动,但是只有时间参数会发现所有的顶点都会有相同的
//偏移,所以这里根据模型空间的原点计算了一个距离dis作为sin的偏移值,这样看起来就是随机漂移的效果了
v2f vert(appdata v) {
v2f o;
float3 offset = float3 (0,0,0);//模型空间原点
float dis = distance(v.vertex.xyz, offset);//计算幅度偏移量
offset.x = sin(_Time.y * _Speed.x + dis);//根据_Speed.x控制x轴速度
offset.y = sin(_Time.y * _Speed.y + dis);//根据_Speed.y控制y轴速度
//根据_Speed.z控制z轴速度。同时_Speed.w 控制Z方向上的偏移距离大小
offset.z = _Speed.w * sin(_Time.y * _Speed.z + dis);
v.vertex.xyz += offset;
//变换到裁剪空间,所有顶点着色都需要此步的计算
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
//这里用unity的宏计算世界空间法线方向,也可以用模型空间到世界空间的逆转置矩阵乘以模型空间法线方
//向获得,即normalize(mul(v.normal,(float3x3)unity_WorldToObject));
float3 normalDir = normalize(UnityObjectToWorldNormal(v.normal));
//等同于先计算世界坐标系顶点信息worldPos,第一个平行光世界位置减worldPos再归一化获得
float3 lightDir = normalize(WorldSpaceLightDir (v.vertex));
//由lambert定律得知,光照强度和法线方向与光照方向的点积结果正相关。结果(-1,1)之间,强制舍弃
//负数部分极为lambert光照模型,通过下面等式把结果映射到(0,1)即为halflambert光照模型。
//lamber是符合物理的的光照算法,但halflambert的效果要好于lambert更符合计算机视觉需求
fixed halflambert = dot(normalDir, lightDir) * 0.5 + 0.5;
//这里通过属性颜色和光照计算最终的颜色。需要光照的原因是效果中有阴暗面的区分,
//也会根据光照方向不同而改变。如果没有光照,这个凹凸不平的透明模型和一个透明的平面没有区别。
fixed3 diffuse = _Diffuse.rgb * halflambert;
//通过属性_Diffuse.a控制透明度,把颜色传给片元着色器
o.color = fixed4(diffuse, _Diffuse.a);
return o;
}
//着片元计算,这里输出顶点中计算好的颜色即可
fixed4 frag(v2f i) : SV_Target {
return i.color;
}
ENDCG
}
}
//当上面shader不管用时的备用着色器
FallBack "Transparent/VertexLit"
}
到此为止,我们就把这个关于顶点漂移的shader写完了,终于理解为什么都说打这么多字还是很不容易的。哈哈,不够效果还可以的^-^。
可以优化的点,失去的是自由度,但效果差别不是很大,可根据需求修改。
float3 offset = float3 (0,0,0);//模型空间原点
float dis = distance(v.vertex.xyz, offset);//计算幅度偏移量
dis= sin(_Time.y * _Speed.x + dis)
offset.x = dis;
offset.y = dis;
//根据_Speed.w 控制Z方向上的偏移距离大小
offset.z = _Speed.w * dis;
最后上一张渣图,效果影响不堪入目。。。
这篇关于UnityShader顶点动画实现Mage-Fiers漂移效果的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!