1.流动的河流
声明所需要的属性:
Properties
{
_MainTex ("Main Tex", 2D) = "white"{}
_Color ("Color", Color) = (1.0, 1.0, 1.0, 1.0)
_Speed ("Speed", float) = 0.5
_Magnitude ("Distortion Magnitude", float) = 1
_Frequency ("Distortion Frequency", float) = 1
_InvWaveLength ("Distortion Inverse Wave Length", float) = 10
}
确定子着色器标签:
Tags { "RenderType"="Transparent"
"Queue"="Transparent"
"IgnoreProjector"="Ture" //是否收到投影影响
"DisableBatching"="True" //阻止 Unity 将动态批处理应用于使用此子着色器的几何体,动态批处理会将几何体转换至世界空间
//从而导致无法访问物体的模型空间,顶点动画需要对模型空间下的顶点偏移,所以需要关闭。
}
在标签中涉及到两个新的标签的声明:
1.IgnoreProjector
2.DisableBatching
pass实现:
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 _Speed;
float _Magnitude;
float _Frequency;
float _InvWaveLength;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
};
v2f vert (appdata v)
{
v2f o;
float4 Offset;
Offset.yzw = float3 (0.0, 0.0, 0.0); //只对x值进行偏移,所以其他分量取零
Offset.x = sin(_Frequency * _Time.y + _InvWaveLength * (v.vertex.x + v.vertex.y + v.vertex.z )) * _Magnitude;
// 利用_Frequency * _Time.y控制正弦函数的频率,为了不同位置有不同位移,加上模型空间的位置分量,并乘以_InvWaveLength控制波长
// 最后对结果值乘以_Magnitude来控制波动幅度。
o.pos = UnityObjectToClipPos(v.vertex + Offset);
o.uv = TRANSFORM_TEX(v.uv, _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
}
}
2.广告牌技术
主要实现:
v2f vert (appdata v)
{
v2f o; //此时还是在模型空间当中
float3 center = float3(0, 0, 0); //选择模型空间下的原点作为锚点
float3 viewer = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos,1)); //获得模型空间下的视向量
float3 normalDir = viewer - center; //视向量减去原点,获得物体的法线
//法线的Y为1时,意味着法线方向固定为视角方向,
//法线的Y为0时,意味着法线在面上,则向上方向固定为(0, 1, 0),朝向视角
normalDir.y = normalDir.y * _VerticalBillboarding;
normalDir = normalize(normalDir); //向量归一化
float3 upDir = abs(normalDir.y) > 0.999 ? float3(0, 0, 1) : float3(0, 1, 0); //通过法线向量不同的Y值获得粗略的向上方向
float3 rightDir = normalize( cross( upDir, normalDir)); //利用叉乘获得向右方向
upDir = normalize( cross( normalDir, rightDir)); //重新叉乘获得向上方向
float3 centerOffs = v.vertex.xyz - center; //获得原始位置相对于锚点的偏移量
float3 localPos = center + rightDir * centerOffs.x + upDir * centerOffs.y + normalDir * centerOffs.z;
o.pos = UnityObjectToClipPos(float4(localPos, 1));
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}