当前位置: 首页 > news >正文

Unity ShaderGraph Input节点实战:用UV和Time节点5分钟做出流动水面效果

Unity ShaderGraph实战:5分钟打造动态水面效果

水面效果是游戏开发中最常见的自然元素之一。想象一下,当玩家走过湖边,看到微风拂过水面泛起的涟漪,或是暴风雨中汹涌的波涛,这些动态效果都能极大提升游戏的沉浸感。传统的水面着色器编写需要深厚的图形学知识,而ShaderGraph让这一切变得可视化且直观。本文将带你用UV和Time这两个核心Input节点,快速实现一个基础但效果出众的动态水面。

1. 准备工作与环境搭建

在开始制作水面效果前,我们需要确保开发环境配置正确。首先创建一个新的URP项目(Universal Render Pipeline),这是Unity推荐的现代渲染管线,对ShaderGraph有更好的支持。

  1. 在Unity Hub中新建项目时选择URP模板
  2. 创建完成后,在项目窗口中右键选择Create > Shader Graph > URP > Unlit Shader Graph(因为我们先实现基础效果,后续可升级为PBR水面)
  3. 将新建的ShaderGraph命名为"WaterSurface"

提示:如果找不到ShaderGraph创建选项,请确保已安装ShaderGraph包(Window > Package Manager中搜索安装)

接下来我们需要准备一张基础水面纹理。可以在任何素材网站搜索"water normal map"找到合适的法线贴图,这将作为我们水面波纹的基础。将下载的贴图导入Unity后,记得在Inspector中将Texture Type设置为Normal map

2. UV动画:创造水面流动感

UV动画是Shader中实现动态效果的核心技术之一。原理很简单:通过随时间改变UV坐标,让贴图"移动"起来。

打开刚创建的WaterSurface ShaderGraph,我们先建立基础的UV流动:

  1. 在空白处右键创建UV节点(Input > Geometry > UV)
  2. 添加Time节点(Input > Basic > Time)
  3. 创建Multiply节点,将Time与一个Vector2常量连接(如(0.02, 0.02)控制速度)
  4. 使用Add节点将UV和乘后的Time相加

此时你的网络应该类似这样:

UV -> Add Time -> Multiply -> Add Vector2(0.02,0.02) -> Multiply

这种基础UV动画会让整个贴图朝右下角匀速移动。但真实的水面运动更加复杂,我们需要更丰富的层次感。

3. 多层纹理混合:增加水面细节

单一方向的流动看起来会很假。专业的水面效果通常使用多层纹理以不同速度和方向混合:

  1. 复制刚才的UV动画网络,创建第二套(建议将速度改为(0.03, -0.01))
  2. 为两套UV网络分别采样不同的法线贴图(可使用同一张贴图但缩放不同)
  3. 添加Blend节点(Normal Blend或Height Blend模式)混合两个法线结果
// 第一层UV动画 UV -> Add1 Time -> Multiply1 -> Add1 Vector2(0.02,0.02) -> Multiply1 // 第二层UV动画 UV -> Add2 Time -> Multiply2 -> Add2 Vector2(0.03,-0.01) -> Multiply2 // 采样与混合 Add1 -> SampleTexture2D1 -> Blend Add2 -> SampleTexture2D2 -> Blend

注意:纹理采样时,建议将Wrap Mode设置为Repeat,这样UV超出1.0时会自动平铺而非拉伸

4. 添加顶点动画:模拟波浪起伏

仅有表面法线变化还不够,真实水面会有高度起伏。我们可以用顶点位移来模拟:

  1. 创建Position节点(Input > Geometry > Position)
  2. 使用之前混合的法线贴图的R或G通道(代表水平方向的高度变化)
  3. 通过Remap节点将法线值从[0,1]映射到[-0.1,0.1]作为位移幅度
  4. 将结果与原始Position相加后输出到Master节点的Position端口
Blend -> Split -> R通道 -> Remap(0,1,-0.1,0.1) -> Add Position -> Add -> Master_Position

为增强效果,可以再添加一个基于世界XZ坐标的Sine波

Position -> Split -> XZ -> Multiply(0.5) -> Sine -> Multiply(0.05) -> Add

这样水面会有基础的大波浪运动,配合之前的细节法线,效果立即生动起来。

5. 镜面反射与边缘光:提升视觉质感

基础动画完成后,我们需要添加光学特性使水面更真实:

  1. 创建Normal Vector节点(使用之前混合的法线结果)
  2. 添加View Direction节点并归一化
  3. 使用Dot Product节点计算视角与法线的夹角
  4. 通过Power节点控制高光强度(如Power=50)
  5. 输出到Master节点的Smoothness和Specular
Blend -> NormalVector -> DotProduct ViewDirection -> Normalize -> DotProduct DotProduct -> Power(50) -> Master_Specular

边缘光(Fresnel效应)可以通过类似方式实现:

NormalVector -> FresnelEffect -> Master_Emission

6. 参数优化与性能考量

现在我们的水面已经具备基本所有元素,最后需要调整参数并考虑性能:

  1. 速度控制:建议将Time乘数设为可调参数(右键Create Property)
  2. 幅度控制:顶点位移和法线强度也应暴露为参数
  3. LOD处理:远处水面可以简化计算
  4. 纹理压缩:确保法线贴图使用适当压缩格式(如BC5/DXT5nm)

参数建议值:

参数建议值说明
速度1(0.02,0.02)基础层流动速度
速度2(0.03,-0.01)细节层流动速度
位移幅度[-0.1,0.1]波浪高度范围
高光强度50-100水面反光程度

在项目中使用时,可以根据相机距离动态调整这些参数,远处水面可以减少纹理层数或禁用顶点动画。

7. 进阶扩展思路

基础效果实现后,可以考虑以下增强方向:

  • 焦散效果:添加Caustics纹理动画模拟水下光斑
  • 泡沫系统:在水体边缘或物体周围添加泡沫痕迹
  • 交互波纹:通过脚本传递物体位置信息生成局部涟漪
  • 天气影响:根据风雨强度参数化控制波浪幅度
  • 深度渐变:浅水区更透明且波浪更明显

实现交互波纹的简单方法:

  1. 在C#脚本中定义可交互物体位置数组
  2. 通过Material.SetVectorArray传递到Shader
  3. 在Shader中计算每个位置的距离并叠加波纹
// C#脚本 public Transform[] interactObjects; private Vector4[] positions; void Update() { positions = interactObjects.Select(t => (Vector4)t.position).ToArray(); material.SetVectorArray("_InteractPositions", positions); }
// Shader中 for(int i=0; i<_Count; i++) { float dist = distance(_InteractPositions[i].xyz, worldPos); float wave = saturate(1-dist/_Radius) * sin(dist*_Frequency - _Time.y*_Speed); height += wave * _Amplitude; }

这种技术可以让角色走过水面时产生真实的涟漪扩散效果。

http://www.jsqmd.com/news/894037/

相关文章:

  • 避开国内网络大坑:手把手教你用清华源和本地包搞定DiffDock环境配置(含dllogger、openfold等疑难杂症解决)
  • 避坑指南:Unity用C#获取系统时间,别忘了时区、性能和格式化这三点!
  • 2026干混砂浆源头直供技术解析与靠谱供应商参考:成都水泥厂家/成都河沙批发/拉法基水泥厂家推荐四川干混砂浆生产厂家/选择指南 - 优质品牌商家
  • Keil C51内存布局控制:指针数组与字符串常量地址固定技巧
  • 数据归一化实战指南:解决特征量纲不一致与模型失效问题
  • Unity编辑器Selection系统深度解析与避坑指南
  • 当每一行代码都可能是“AI代笔”:你会为“零AI介入”的汽车支付溢价吗?
  • SAP MIRO发票校验时,如何用增强LMR1M001自动拦截供应商信息错误?
  • LLM安全攻防:对抗攻击原理与防御实践
  • 2026年Q2智慧酒店OLT光网系统专业厂家排行:智慧酒店RCU客房控制系统、智慧酒店升级改造方案及报价、智慧酒店客房系统选择指南 - 优质品牌商家
  • QMCDecode终极指南:免费快速解锁QQ音乐加密格式的完整教程
  • 从地理空间数据云到可游玩地图:一份给独立开发者的真实世界地形创建全流程指南
  • 告别GPIO模拟时序!用STM32的FSMC外设驱动TFTLCD,为什么又快又省事?
  • PyTorch多GPU训练避坑指南:CUDA_VISIBLE_DEVICES和DataParallel的正确打开方式
  • Burp插件实现验证码接口行为测绘与爆破
  • 图解First-Fit算法:手把手带你实现ucore Lab 2的物理内存分配器
  • 避坑指南:YOLOv8转TensorRT引擎(.engine)后,在Jetson TX2上推理的后处理细节与性能调优
  • 告别无限循环!UE4粒子特效Cascade模块详解:从Required到Lifetime的避坑配置指南
  • AI智能体持久记忆系统构建:从RAG架构到向量数据库实战
  • 基于CLIP与BERT的多模态假新闻检测:特征对齐与层次化融合实战
  • 【AI面试临阵磨枪-73】金融 AI 安全:风控、反欺诈、合规、幻觉、隐私保护
  • 07.Day 7:植入顶级大脑 —— PEAK 框架与多维 ABLE 假设工程
  • AI写作会跟别人重复吗?2026年深度解析+4个方法告别内容模板化
  • Android开发板与Windows网络不通?原来是策略路由在作祟
  • 融合ILC与扭矩库的腿式机器人自适应控制方法
  • YOLO26实现布料缺陷自动化检测(项目源码+数据集+模型权重+UI界面+python+深度学习+远程环境部署)
  • 终极指南:如何部署和配置企业级开源ITSM平台
  • 别再硬编码了!用HTN框架5分钟搞定游戏AI的‘最优路径’决策(附Unity/Unreal插件对比)
  • Linux timeout命令的隐藏玩法:不只是限时,还能优雅终止和前台调试
  • 基于嵌入式MTJ的p-bit硬件实现:用成熟技术开启概率计算新范式