《Shader入门精要》第11章-11.3.1流动的河流中的offset.x的解释

在我学习入门精要的时候,经常遇到不解释api,甚至是关键代码的实现原理。
11.3.1流动的河流中的offset.x的sin函数查了一下好像大家也都是书上原话直接复制,现在好不容易想明白了希望能帮到和我一样一脸懵逼的人。

// 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.5
	}
	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;
			fixed4 _Color;
			float _Magnitude;
			float _Frequency;
			float _InvWaveLength;
			float _Speed;
			
			struct a2v {
				float4 vertex : POSITION;
				float4 texcoord : TEXCOORD0;
			};
			
			struct v2f {
				float4 pos : SV_POSITION;
				float2 uv : TEXCOORD0;
			};
			
			v2f vert(a2v 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;
				o.pos = UnityObjectToClipPos(v.vertex + offset);
				//这里只对uv偏移,对模型顶点没有影响
				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 "Transparent/VertexLit"
}

这个offset.x是个啥?而且其中的v.vertex的xyz分量都乘了波长更让人摸不着头脑,我们先看一个标准版本。
下面这个版本能够实现一个标准的行波河流

offset.x = _Magnitude * sin(_Frequency * _Time.y + v.vertex.z * _InvWaveLength);

效果(上下边缘对称)
在这里插入图片描述

然后逐一解释
这个首先是坐标,我们需要知道模型空间下左右(横轴)是z,而上下是x。

然后再用行波的表达式

y = Asin(kx - ωt + φ)+ b

可以知道x对应v.vertex.z;_Time.y对应t

并且周期是2π/ω,波长是2π/k。

那么我们就能知道书上原话“利用_Frequency属性和内置的_Time变量来控制正弦函数的频率,…乘以_InvWaveLength来控制波长”是啥意思了
_Magnitude 控制波动幅度大家学过三角函数肯定都知道。

然后再来看书上为什么是

offset.x = sin(_Frequency * _Time.y + v.vertex.x * _InvWaveLength + v.vertex.y * _InvWaveLength + v.vertex.z * _InvWaveLength) * _Magnitude;

这里多出来的是
v.vertex.y * _InvWaveLength + v.vertex.x * _InvWaveLengt
实际上y没有意义----因为我们这个河流的顶点的y在模型空间上都是0
所以考虑x就是在纵方向上形成偏移,竖直方向来看,同一z轴的x往下不断变化,也就是同一z上的不同x的初项不同,从上往下的波初项不同,形成偏移
放在图片上面就是上下边缘的波形相同,但是时刻不同。

这里可能有人想的比较复杂,觉得顶点坐标已经偏移了之后计算会变化,但其实v.vertex一直都是原本的顶点坐标,只是pos来负责计算之后输出到SV_POSITION之中。
在这里插入图片描述
希望能帮到大家

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值