UnityShader 顶点动画
顶点动画是在顶点着色器中对顶点先进行偏移,然后做MVP变化,来模拟动画效果。
Shader "Custom/WaterMat"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_WaveSpeed("WaveSpeed", float) = 1
_WaveScale("WaveScale", float) = 10
}
SubShader
{
Tags { "RenderType"="Opaque" "DisableBatching" = "True"}
Cull Off
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _WaveScale;
float _WaveSpeed;
v2f vert (appdata v)
{
v2f o;
float offset = sin(_Time.y * _WaveSpeed + v.vertex.z * _WaveScale) * 2;
o.vertex = UnityObjectToClipPos(v.vertex + float4(offset, 0, 0, 0));
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}
实例中使用Plane模型实现,如果使用Quad模型则无法达到理想的效果,原因是Quad模型是由两个三角形四个顶点组成的,顶点太少无法形成波浪效果,而Plane模型的网格是由多个三角形组成的。
广告牌技术(BIllBoarding)
广告牌技术会根据视角的方向旋转一个被纹理着色的多边形,通过.Shader对顶点进行变化,而不需要通过C#脚本改变模型的rotation。
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
Shader "Custom/BillBoardingMat"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_VerticalBillBoarding("Vertical BillBoarding", Range(0, 1.0)) = 1
}
SubShader
{
Tags { "RenderType"="Opaque"}
Pass
{
ZWrite Off
Cull Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
float _VerticalBillBoarding;
v2f vert (appdata v)
{
v2f o;
float3 center = float3(0, 0, 0);
float3 viewPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos, 1));
float3 viewDir = viewPos - center;
float3 upDir = abs(viewDir.y) > 0.999 ? float3(0, 0, 1) : float3(0, 1, 0);
viewDir.y = viewDir.y * _VerticalBillBoarding;
float3 rightDir = normalize(cross(upDir, viewDir));
upDir = normalize(cross(viewDir, rightDir));
float3 transPos = center + upDir * v.vertex.y + viewDir.z * v.vertex.z + rightDir * v.vertex.x;
o.vertex = UnityObjectToClipPos(float4(transPos, 1));
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}
使用这种技术可以使用2D纹理在较远的距离下较为真实的模拟3D物体,有效节省了运行内存和GPU算力。
实现:通过视角方向和模糊的向上方向获得一个面向摄像机的三维标准坐标系,将原顶点位置经过该坐标系转换到该坐标系下与原坐标系相同的位置。
顶点动画与阴影
具有顶点动画的材质虽然材质顶点发生了偏移,但绘制阴影的时候使用的是未进行偏移的顶点。
如果需要得到偏移后的顶点绘制的阴影,需要提供自定义的ShaderCaster Pass,将顶点偏移后传入TRANSFER_SHADER_CASTER_NORMALOFFSET(o)。