49.动态效果-顶点动画-滚动的2D河流-具体实现
49.1 知识点
知识回顾
实现 2D 河流效果的关键公式:
某轴位置偏移量 = sin(_Time.y * 波动频率 + 顶点某轴坐标 * 波长的倒数) * 波动幅度
知识补充:关闭批处理
渲染标签设置
"DisableBatching" = "True"
主要作用
- 是否对 SubShader 关闭批处理。
- 在制作顶点动画时,可能需要关闭 Shader 的批处理:
- 因为顶点动画经常使用模型空间下的数据。
- 批处理会合并所有相关模型,导致模型空间数据丢失,无法正确应用。
- 在实现 2D 河流效果时,需要让顶点在模型空间下偏移,因此需使用该标签关闭 Shader 的批处理。
导入资源 观察资源
导出测试用资源,观察资源模型空间轴向。该模型的模型空间坐标并不符合Unity轴向标准,它的上下是x轴 左右是z轴 前后是y轴。旋转他子对象让他符合标准
流动的 2D 河流效果:具体实现
主要步骤
- 新建 Shader 文件并清理掉无用代码,保留必要的框架结构。
- 声明属性和映射属性,包括:
- 主纹理 (_MainTex)
- 叠加颜色 (_Color)
- 波动幅度 (_WaveAmplitude)
- 波动频率 (_WaveFrequency)
- 波长的倒数 (_InvWaveLength)
- 配置透明 Shader 的相关参数:
- 渲染标签设置:
Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "DisableBatching"="True"}
- 深度写入与透明混合设置:
ZWrite Off Blend SrcAlpha OneMinusSrcAlpha
- 渲染标签设置:
- 定义结构体,包含顶点位置和 UV 坐标。
- 编写顶点着色器:
- 使用理论公式计算指定轴的偏移量。
- 注意偏移操作需在模型空间中进行。
- 编写片元着色器:
- 对纹理颜色进行采样。
- 将采样的颜色与叠加颜色进行融合并输出。
创建 Shader 骨架
Shader "Unlit/Lesson49_2DWater"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
ENDCG
}
}
}
声明属性、映射属性包括主纹理(_MainTex),叠加的颜色(_Color),波动幅度(_WaveAmplitude),波动频率(_WaveFrequency)和波长的倒数(_InvWaveLength),也可以加上纹理移动速度,让纹理和顶点都动,效果更好
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
//波动幅度
_WaveAmplitude("WaveAmplitude", Float) = 1
//波动频率
_WaveFrequency("WaveFrequency", Float) = 1
//波长的倒数
_InvWaveLength("InvWaveLength", Float) = 1
//纹理变化速度
_Speed("Speed", Float) = 1
}
// 2D 纹理采样器
sampler2D _MainTex;
// 纹理的缩放和平移信息
float4 _MainTex_ST;
// 颜色值,用于调整纹理颜色
float4 _Color;
// 波浪的振幅
float _WaveAmplitude;
// 波浪的频率
float _WaveFrequency;
// 波浪的倒数波长
float _InvWaveLength;
// 纹理移动速度
float _Speed;
设置透明Shader相关,设置相关渲染标签,关闭深度写入开启透明混合
// 透明 Shader 相关渲染标签 + 关闭批处理标签
Tags
{
// 设置渲染类型为透明 因为可能会在水中悬浮
"RenderType"="Transparent"
// 设置渲染队列顺序为透明队列
"Queue"="Transparent"
// 忽略投影器
"IgnoreProjector"="True"
// 关闭批处理
"DisableBatching"="True"
}
Pass
{
// 关闭深度写入
ZWrite Off
// 设置混合模式为源颜色的透明度作为混合因子,目标颜色的(1 - 源颜色透明度)作为混合因子
Blend SrcAlpha OneMinusSrcAlpha
//...
}
结构体无需改动,包括纹理坐标和裁剪坐标即可
struct v2f
{
// 纹理坐标,用于传递给片元着色器进行纹理采样
float2 uv : TEXCOORD0;
// 顶点在裁剪空间中的位置
float4 vertex : SV_POSITION;
};
顶点函数中,利用理论中讲解的公式,计算对应轴向偏移位置。注意,是在模型空间中偏移。为了效果更好可以加上时间对纹理的移动
// 顶点着色器函数
v2f vert(appdata_base appdata_base)
{
v2f v2f;
// 模型空间下的偏移位置
float4 offset;
// 让它在模型空间的 x 轴方向进行偏移 因为x是长的横的 基于预制体定的
// 河流公式:某轴位置偏移量 = sin(_Time.y * 波动频率 + 顶点某轴坐标 * 波长的倒数) * 波动幅度
offset.x = sin(_Time.y * _WaveFrequency + appdata_base.vertex.z * _InvWaveLength) * _WaveAmplitude;
offset.yzw = float3(0, 0, 0);
// 将顶点从模型空间转换到裁剪空间,并加上偏移量
v2f.vertex = UnityObjectToClipPos(appdata_base.vertex + offset);
// 计算纹理坐标,结合纹理的缩放和平移信息以及模型的原始纹理坐标
v2f.uv = appdata_base.texcoord * _MainTex_ST.xy + _MainTex_ST.zw;
// 根据时间和速度在垂直方向上移动纹理坐标
v2f.uv += float2(0, _Time.y * _Speed);
return v2f;
}
片元函数中采样乘上我们设置好的颜色并返回
// 片元着色器函数
fixed4 frag(v2f v2f) : SV_Target
{
// 对纹理进行采样
fixed4 color = tex2D(_MainTex, v2f.uv);
// 将采样得到的颜色的 RGB 分量乘以指定的颜色值,实现颜色调整
color.rgb *= _Color.rgb;
return color;
}
创建材质赋值可以查看水流的效果
49.2 知识点代码
Lesson49_动态效果_顶点动画_滚动的2D河流_具体实现.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson49_动态效果_顶点动画_滚动的2D河流_具体实现 : MonoBehaviour
{
void Start()
{
#region 知识回顾
//实现2D河流效果的关键公式:
//某轴位置偏移量 = sin(_Time.y * 波动频率 + 顶点某轴坐标 * 波长的倒数) * 波动幅度
#endregion
#region 知识补充 关闭批处理
//渲染标签
//"DisableBatching" = "True"
//主要作用:
//是否对SubShader关闭批处理
//我们在制作顶点动画时,有时需要关闭该Shader的批处理
//因为我们在制作顶点动画时,有时需要使用模型空间下的数据
//而批处理会合并所有相关的模型,这些模型各自的模型空间会丢失,导致我们无法正确使用模型空间下相关数据
//在实现流程的2D河流效果时,我们就需要让顶点在模型空间下进行偏移
//因此我们需要使用该标签,为该Shader关闭批处理
#endregion
#region 知识点一 导入资源 观察资源
//1.导出测试用资源
//2.观察资源模型空间轴向
// 该模型的模型空间坐标并不符合Unity轴向标准
// 它的上下是x轴 左右是z轴 前后是y轴
#endregion
#region 知识点二 流动的2D河流效果 具体实现
//1.新建Shader,删除无用代码
//2.声明属性、映射属性
// 主纹理(_MainTex)
// 叠加的颜色(_Color)
// 波动幅度(_WaveAmplitude)
// 波动频率(_WaveFrequency)
// 波长的倒数(_InvWaveLength)
//3.透明Shader相关
// 渲染标签相关
// Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "DisableBatching"="True"}
// 深度写入、透明混合相关
// ZWrite Off
// Blend SrcAlpha OneMinusSrcAlpha
//4.结构体相关
// 顶点和uv
//5.顶点着色器
// 利用理论中讲解的公式,计算对应轴向偏移位置
// 注意,在模型空间中偏移
//6.片元着色器
// 直接进行颜色采样,颜色叠加
#endregion
}
}
Lesson49_2DWater.shader
Shader "Unlit/Lesson49_2DWater"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
//波动幅度
_WaveAmplitude("WaveAmplitude", Float) = 1
//波动频率
_WaveFrequency("WaveFrequency", Float) = 1
//波长的倒数
_InvWaveLength("InvWaveLength", Float) = 1
//纹理变化速度
_Speed("Speed", Float) = 1
}
SubShader
{
// 透明 Shader 相关渲染标签 + 关闭批处理标签
Tags
{
// 设置渲染类型为透明 因为可能会在水中悬浮
"RenderType"="Transparent"
// 设置渲染队列顺序为透明队列
"Queue"="Transparent"
// 忽略投影器
"IgnoreProjector"="True"
// 关闭批处理
"DisableBatching"="True"
}
Pass
{
// 关闭深度写入
ZWrite Off
// 设置混合模式为源颜色的透明度作为混合因子,目标颜色的(1 - 源颜色透明度)作为混合因子
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
// 2D 纹理采样器
sampler2D _MainTex;
// 纹理的缩放和平移信息
float4 _MainTex_ST;
// 颜色值,用于调整纹理颜色
float4 _Color;
// 波浪的振幅
float _WaveAmplitude;
// 波浪的频率
float _WaveFrequency;
// 波浪的倒数波长
float _InvWaveLength;
// 纹理移动速度
float _Speed;
struct v2f
{
// 纹理坐标,用于传递给片元着色器进行纹理采样
float2 uv : TEXCOORD0;
// 顶点在裁剪空间中的位置
float4 vertex : SV_POSITION;
};
// 顶点着色器函数
v2f vert(appdata_base appdata_base)
{
v2f v2f;
// 模型空间下的偏移位置
float4 offset;
// 让它在模型空间的 x 轴方向进行偏移 因为x是长的横的 基于预制体定的
// 河流公式:某轴位置偏移量 = sin(_Time.y * 波动频率 + 顶点某轴坐标 * 波长的倒数) * 波动幅度
offset.x = sin(_Time.y * _WaveFrequency + appdata_base.vertex.z * _InvWaveLength) * _WaveAmplitude;
offset.yzw = float3(0, 0, 0);
// 将顶点从模型空间转换到裁剪空间,并加上偏移量
v2f.vertex = UnityObjectToClipPos(appdata_base.vertex + offset);
// 计算纹理坐标,结合纹理的缩放和平移信息以及模型的原始纹理坐标
v2f.uv = appdata_base.texcoord * _MainTex_ST.xy + _MainTex_ST.zw;
// 根据时间和速度在垂直方向上移动纹理坐标
v2f.uv += float2(0, _Time.y * _Speed);
return v2f;
}
// 片元着色器函数
fixed4 frag(v2f v2f) : SV_Target
{
// 对纹理进行采样
fixed4 color = tex2D(_MainTex, v2f.uv);
// 将采样得到的颜色的 RGB 分量乘以指定的颜色值,实现颜色调整
color.rgb *= _Color.rgb;
return color;
}
ENDCG
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com