|
Part 4:顶点动画
效果依旧不是很特别,因为现在可以接收并处理粒子系统的输入颜色,所以我们可以通过将Start Color恢复为纯白色,注释掉将col插补为红色的代码,并使用Color over Lifetime模块在标准化粒子生命周期将红色过渡为蓝色,从而获得完全相同的结果。
如果我们只是为了制作一个自定义着色器,它应该能实现更多功能。现在我们要实现无法通过修改组件设置或在CPU编程来轻松实现的效果。
我们已经学习如何使用自定义顶点流处理渲染粒子的像素。接下来处理它的顶点。在顶点部分中,在修改位置的代码前,即代码o.vertex = UnityObjectToClipPos(v.vertex),添加这部分代码。
// 奇怪的顶点动画
float sineFrequency = 5.0;
float sineAmplitude = 4.0;
float sineOffset = sin(_Time.y * sineFrequency) * sineAmplitude;
float agePercent = v.uv.z;
float3 vertexOffset = float3(0, sineOffset * agePercent, 0);
v.vertex.xyz += vertexOffset;
注意:_Time是Unity着色器内置的4D变量,_Time的Y值没有更改。我们也可以使用_SinTime.w,它是未更改的时间正弦。
我们使用正弦波创建了动画,其中Y偏移被调整为正弦偏移和粒子寿命的乘积。粒子寿命越大,偏移越大,于是得到了下图效果。
通过将基础粒子系统改为粒子弹簧,我们可以让效果没那么奇怪。在得到正常运行的顶点动画后,为粒子系统实现粒子弹簧效果非常简单。
Part 5:粒子弹簧
首先,新粒子系统的默认Rotation X值为-90,请确保将其重置为0。
在Main模块,勾选Prewarm,将Start Lifetime设为4,Start Speed设为0。
完全禁用Shape模块。因为我们想要完美的点发射器。
最后启用Velocity over Lifetime模块,并按下图进行设置。Linear Y设为2,Orbital Y设为8,Offset X设为1。这样一来,粒子会上升,绕着本地Y轴,将Space设为Local旋转,由于旋转中心在X轴偏移1个单位,它会实现螺旋图案。
通过修改以上设置,我们可以控制弹簧的外形。
下图是得到的效果,弹簧会上下移动。
如果想要多个弹簧粒子,应该怎样处理呢?因为该着色器使用和噪声相同的输入,无论材质如何,每个弹簧都有相同的动画效果。我们需要一种方法来根据材质指定偏移。
现在返回到着色器代码,在主纹理下添加偏移时间的新属性。我们在此创建了一个数值滑块,调整范围在0.0和100.0之间,默认值为0.0,即无偏移。
_MainTex("Texture", 2D) = "white" {}
_TimeOffset("Noise Offset", Range(0, 100)) = 0.0
然后,添加时间偏移变量。
sampler2D _MainTex;
float4 _MainTex_ST;
uniform float _TimeOffset;
最后将偏移值与_Time.y相加,将得到的结果存为新变量,以使代码更清楚,接下来将该变量传到正弦函数中,使它在函数中与频率相乘。
float time = _Time.y + _TimeOffset;
float sineOffset = sin(time * sineFrequency) * sineAmplitude;
现在,我们只需要复制粒子系统和材质,然后修改刚添加的偏移属性即可。创建当前粒子系统的副本,然后确保每个副本有独特的材质和不同的偏移值,并使用相同的着色器。
我们完成的效果如下图所示。
着色器代码
完整的着色器代码如下。
Shader "Unlit/Simple Particle Unlit"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
_TimeOffset("Noise Offset", Range(0, 100)) = 0.0
}
SubShader
{
Tags { "Queue" = "Transparent" "RenderType" = "Opaque" }
LOD 100
Blend One One // 加法混合
ZWrite Off // 关闭深度测试
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// 实现模糊效果
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
fixed4 color : COLOR;
float3 uv : TEXCOORD0;
};
struct v2f
{
float3 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _TimeOffset;
v2f vert(appdata v)
{
v2f o;
// 奇怪的定点动画
float sineFrequency = 5.0;
float sineAmplitude = 4.0;
float time = _Time.y + _TimeOffset;
float sineOffset = sin(time * sineFrequency) * sineAmplitude;
float agePercent = v.uv.z;
float3 vertexOffset = float3(0, sineOffset * agePercent, 0);
v.vertex.xyz += vertexOffset;
o.vertex = UnityObjectToClipPos(v.vertex);
// 从保存在颜色顶点输入的粒子系统接收数据,并将该数据用于初始化颜色
o.color = v.color;
o.uv.xy = TRANSFORM_TEX(v.uv, _MainTex);
// 初始化tex coord变量
o.uv.z = v.uv.z;
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target
{
//采样纹理
fixed4 col = tex2D(_MainTex, i.uv);
// 让纹理颜色和粒子系统的顶点颜色输入相乘
col *= i.color;
float particleAgePercent = i.uv.z;
float4 colourRed = float4(1, 0, 0, 1);
// 根据粒子寿命百分比,从纹理颜色插值为红色
col = lerp(col, colourRed * col.a, particleAgePercent);
// 应用模糊效果
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
} |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|