当为顶点做动画的时候就需要关闭批处理,因为批处理会合并所有相关的模型,而这些模型会失去各自的模型空间。下面的例子中因为需要对顶点进行操作,所以要关闭批处理。
强制关闭批处理会增加drawcall,一般来说需要尽量减少此类操作。
效果如下,说明都在代码注释里了:
Shader "Custom/TestShader27" {
Properties {
//流动纹理
_MainTex ("Main Tex", 2D) = "white" {}
//影响颜色
_Color("Color Tint",Color)=(1,1,1,1)
//幅度
_Magnitude("Distortion Magnitude" ,Float)=1
//波动频率
_Frequency("Distortion Frequency",Float)=1
//波长倒数
_InvWaveLength("Distortion Ivnverse Wave Length",Float)=10
//速度
_Speed("Speed",Float)=0.5
}
SubShader {
//DisableBatching关闭批处理
Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "DisableBatching"="True"}
Pass{
Tags{"LightMode"="ForwardBase"}
ZWrite off
Blend SrcAlpha OneMinusSrcAlpha
Cull off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
float _Magnitude;
float _Frequency;
float _InvWaveLength;
float _Speed;
struct a2v{
float4 vertex:POSITION;
float4 texcoord:TEXCOORD0;
};
struct v2f{
float4 pos:SV_POSITION;
float uv:TEXCOORD0;
};
v2f vert(a2v v){
v2f o;
float4 offset= float4(0.0,0.0, 0.0, 0.0);
//波动更具时间变化 乘以三个分量使的左形成错落感
offset.x = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;
o.pos = UnityObjectToClipPos(v.vertex + offset);
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.uv += float2(0.0, _Time.y * _Speed);
return o;
}
fixed4 frag(v2f i):SV_Target{
fixed4 c = tex2D(_MainTex, i.uv);
c.rgb *= _Color.rgb;
return c;
}
ENDCG
}
}
FallBack "off"//"Transparent/VertexLit"
}
扩展
下面是一个扩展,添加了高光和透明度
Shader "Custom/TestShader27" {
Properties {
//流动纹理
_MainTex ("Main Tex", 2D) = "white" {}
//影响颜色
_Color("Color Tint",Color)=(1,1,1,1)
//幅度
_Magnitude("Distortion Magnitude" ,Float)=1
//波动频率
_Frequency("Distortion Frequency",Float)=1
//波长倒数
_InvWaveLength("Distortion Ivnverse Wave Length",Float)=10
//速度
_Speed("Speed",Float)=0.5
_Specular("_Specular Color",Color)=(1,1,1,1)
_Alpha("Alpha",Range(0,1))=0.5
_Gloss("Gloss",Float)=20
}
SubShader {
//DisableBatching关闭批处理
Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "DisableBatching"="True"}
Pass{
Tags{"LightMode"="ForwardBase"}
ZWrite off
Blend SrcAlpha OneMinusSrcAlpha
Cull off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Lighting.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
float4 _Color;
float _Magnitude;
float _Frequency;
float _InvWaveLength;
float _Speed;
float _Alpha;
float4 _Specular;
float _Gloss;
struct a2v{
float4 vertex:POSITION;
float4 texcoord:TEXCOORD0;
float4 normal:NORMAL;
};
struct v2f{
float4 pos:SV_POSITION;
float uv:TEXCOORD0;
float3 color:COLOR;
};
v2f vert(a2v v){
v2f o;
float4 offset= float4(0.0,0.0, 0.0, 0.0);
//波动更具时间变化 乘以三个分量使的左形成错落感
offset.y = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;
o.pos = UnityObjectToClipPos(v.vertex + offset);
//改变法线位置
float4 normalOffset = v.normal;
normalOffset.x =sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;
normalOffset.z =sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;
//添加高光
fixed3 worldNormal = normalize(mul(normalOffset,(float3x3)unity_WorldToObject));
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz-mul(unity_ObjectToWorld,v.vertex).xyz);
fixed3 reflectDir = normalize(reflect(-worldLightDir,worldNormal));
fixed3 specular = _LightColor0.rgb * _Specular.rgb *pow(saturate(dot(reflectDir,viewDir)),_Gloss);
o.color = specular*_Specular;
o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
o.uv += float2(0.0, _Time.y * _Speed);
return o;
}
fixed4 frag(v2f i):SV_Target{
fixed3 c = tex2D(_MainTex, i.uv);
c.rgb *= _Color.rgb;
float3 oc = c+i.color;
return float4(oc,_Alpha);
}
ENDCG
}
}
FallBack "off"//"Transparent/VertexLit"
}
阴影
一个Pass的代码,他放在前面代码的后面即可以得到阴影
Pass {
Tags { "LightMode" = "ShadowCaster" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
float _Magnitude;
float _Frequency;
float _InvWaveLength;
float _Speed;
struct v2f {
//用于定义投射需要的变量
V2F_SHADOW_CASTER;
};
v2f vert(appdata_base v) {
v2f o;
float4 offset;
offset.yzw = float3(0.0, 0.0, 0.0);
offset.x = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;
v.vertex = v.vertex + offset;
//让Unity自动完成投射
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
fixed4 frag(v2f i) : SV_Target {
//自动完成阴影投射相关的计算
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}