Shader学习的基础知识(十八)顶点动画

当为顶点做动画的时候就需要关闭批处理,因为批处理会合并所有相关的模型,而这些模型会失去各自的模型空间。下面的例子中因为需要对顶点进行操作,所以要关闭批处理。
强制关闭批处理会增加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
		}
	}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小盖子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值