我的shader学习之三

本篇文章依然是读书笔记。

本文主要写的是unity uv动画相关的内容。

主要是基于unity提供的内置的_Time变量。

代码如下:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Unity Shaders Book/Chapter 11/Water" {
	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 Inverse Wave Length", Float) = 10
 		_Speed ("Speed", Float) = 0.01
	}
	SubShader {
		// Need to disable batching because of the vertex animation
		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;					//这个用于unity的TRANSFORM_TEX,取xy为缩放,zw为偏移
			fixed4 _Color;
			float _Magnitude;				//振幅
			float _Frequency;				//这个是变化频率。即控制sin函数的参数变化速率
			float _InvWaveLength;			//当time为0的时候这个就是Sin函数的初始值,我觉得不是那么有用
			float _Speed;					//uv变化speed,如果没有这个,就只有顶点呈sin函数,没有uv采样的变化	
			
			struct a2v {
				float4 vertex : POSITION;			//模型空间的位置
				float4 texcoord : TEXCOORD0;		//纹理
			};
			
			struct v2f {
				float4 pos : SV_POSITION;			//裁剪空间坐标
				float2 uv : TEXCOORD0;				//uv坐标,用于纹理采样 [0-1]
			};
			
			v2f vert(a2v v) {
				v2f o;
				
				float4 offset;
				offset.yzw = float3(0.0, 0.0, 0.0);
				//经过咨询unity shader里单独有的_Time这个东西,其他引擎估计也有不过我暂时不知道
				//offset.x = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;
				offset.x = sin(_Frequency * _Time.y + v.vertex.z * _InvWaveLength) * _Magnitude;		//为什么这里是对x进行offset,如果你打开这个场景就明白了
				//使用这个x根本不是固定的。我们可以看到在unity的这个模型视图里其x轴垂直向下,z是水平方向,y是向屏幕内的
				//那么这里只是因为坐标轴的原因我们来调整x的offset,实际上如果我们想做旗子的效果,那就是在y轴上offset,如果想做左右跳动的效果,那在这个模型上就是做左右的offset
				//这个offset是周期性的,所以使用正弦函数,实际上这里用我注释的代码是一样的效果,但是如果想做出不同的波段,那么就要用到y和z,因为三条水波的y轴都不一样(z其实一样)
				o.pos = UnityObjectToClipPos(v.vertex + offset);			//这个应该是mvp矩阵变换,将顶点模型空间坐标转换到裁剪空间
				
				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
				o.uv +=  float2(0.0, _Time.y * _Speed);			//uv做一个v的位移,大概是世界乘以速度,问题是uv增加不会到头吗到1
				
				return o;
			}
			
			fixed4 frag(v2f i) : SV_Target {
				fixed4 c = tex2D(_MainTex, i.uv);				//纹理取样
				c.rgb *= _Color.rgb;
				
				return c;
			} 
			
			ENDCG
		}
	}
	FallBack "Transparent/VertexLit"
}

核心的内容是在vertex shader里去计算顶点的偏移量。这里使用的是x坐标,并不是什么特殊原因,是该unity场景的特殊性导致的。只要是垂直方向的offset即可,不一定是x,然后根据时间去计算uv,在片段着色器中纹理取样,然后再乘上本身的rgb值

接下来看一下offset的计算,我们有3条水纹,3条水纹的振幅和频率必须不同,这里使用的其实也是基于坐标的不同

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值