Imported from Orange-Org-0/URP_Shaders (
Assets/StylizedWater/AGENTS.md). Install upstream withnpx skills add Orange-Org-0/URP_Shaders --skill StylizedWater. Copyright stays with the author.
tylized Interactive Water — Agent Instructions
项目目标
在 Unity 2022.3 LTS + URP + Amplify Shader Editor(ASE) 中制作一套可维护、可调节的风格化交互水体。
目标效果包括:
- 深浅水颜色过渡;
- 水面与不透明场景几何体之间的交界泡沫;
- 基于屏幕颜色的风格化伪折射;
- 滚动噪声和法线形成的水面流动;
- 角色或物体移动时产生、扩散并衰减的交互涟漪;
- 面向游戏实时运行的合理性能和清晰的调参入口。
参考思路来自 Minions Art 的 “Shader Graph Interactive Water” 教程,但不要逐节点照抄。应复现其系统架构,并根据当前项目的美术方向重新设计颜色、噪声、泡沫和涟漪表现:
https://www.patreon.com/minionsart/posts/shader-graph-30490169
该教程的 2019 原版更接近 Unity 2022 的实现环境;页面中的 Unity 6.4 更新版只能作为设计参考,不要假设其 Shader Graph 文件可以向下兼容 Unity 2022。
开始工作前
在修改任何内容前,先确认并汇报:
- 当前项目的准确 Unity 版本;
- 当前 URP 和 ASE 版本;
- URP Asset、Renderer、目标平台和颜色空间;
- 是否已启用或可启用 Depth Texture 与 Opaque Texture;
- 项目现有的水体、Shader、材质、渲染层和目录规范;
- 工作区中是否存在用户尚未提交的修改。
优先沿用项目现有结构和命名。除非项目中没有适合的位置,否则不要擅自建立新的顶层目录。
不要直接升级 Unity、URP、ASE 或其他包。发现版本能力不足时,先说明限制和备选方案。
核心认知
这不是流体模拟系统,而是一套实时视觉合成系统。
系统职责应保持分离:
- Particle System:生成扩散、衰减的交互涟漪形状;
- 正交相机 + RenderTexture:记录角色附近的交互信息;
- 脚本:向 Shader 提供交互纹理、捕获区域位置和范围;
- 场景深度:提供水深和水面交界信息;
- Opaque Texture / Scene Color:提供伪折射所需的背景画面;
- ASE 水面 Shader:读取、塑形并合成上述信息;
- 材质参数:向美术提供稳定、含义清楚的调节入口。
不要让 Shader 承担角色追踪、碰撞检测或交互状态管理。
水面 Shader 的模块划分
ASE 图应按以下视觉职责组织。使用 Comment、分组和清楚的连线方向,避免形成无法审查的巨型节点网。
1. Base Surface
负责基础水色、透明度、光滑度,以及整体风格基调。
2. Depth Color
使用水面深度与场景深度之间的差值,在浅水色和深水色之间过渡。
这里得到的是沿摄像机视线方向的屏幕空间深度差,不是真实的三维水深。不要将其描述为物理准确的水体厚度。
3. Intersection Foam
使用 ASE Depth Fade 或等价深度差生成水面与场景几何体的交界遮罩:
- 交界处应得到高值;
- 远离交界处应衰减;
- 使用噪声和可控阈值打破均匀轮廓;
- 保留一层稳定的主体泡沫,避免噪声把泡沫完全切碎。
Depth Fade 的默认输出通常在交界处接近 0,因此制作泡沫遮罩时通常需要反转或重新映射。
4. Refraction
读取 Opaque Texture 或与当前 URP/ASE 模板兼容的场景颜色输入,并用低频噪声、法线或涟漪对屏幕 UV 进行小幅偏移。
这是屏幕空间伪折射,不是真实折射。偏移必须受控,避免水面上方物体被明显错误扭曲。若当前渲染路径不能可靠区分水上和水下内容,先实现保守版本,再提出需要深度判断或自定义渲染通道的改进方案。
5. Surface Motion
使用至少两组方向、速度或尺度不同的世界空间噪声,减少明显的单向纹理滑动感。根据美术需求将其用于:
- 法线;
- 光滑度;
- 颜色轻微变化;
- 折射偏移。
不要让同一份高强度噪声同时驱动所有通道。
6. Interaction Ripples
读取交互 RenderTexture,并把水面世界坐标转换为捕获纹理 UV。该模块只负责解释交互纹理,不负责生成交互。
涟漪至少可以影响:
- 颜色或泡沫高光;
- Emission;
- 折射偏移;
- 可选的法线扰动。
不同影响应拥有独立强度,避免一个总强度参数控制所有表现。
7. Final Composition
最后才组合基础水色、深度色、泡沫、涟漪、折射、法线、光滑度、Emission 和 Alpha。
先保留清晰的中间遮罩,再进行最终合成。不要在图的前半段过早混合所有信号。
Depth Fade 与透明渲染约束
必须明确以下事实:
- Depth Fade 比较当前水面深度与深度缓冲中已有的场景深度;
- 水面通常应位于 Transparent Queue,并且不写入深度;
- 水底、岸边、石头等需要被检测的对象必须写入深度;
- 两个普通的
ZWrite Off半透明对象之间无法获得可靠的 Depth Fade; - 改变 Transparent Queue 顺序本身不能补回缺失的深度;
- 如果必须支持透明物体与水面的深度交互,应单独评估深度代理、透明深度预通道、自定义深度纹理或 Renderer Feature。
不要通过无说明地强制透明水面 ZWrite On 来“修复”Depth Fade,因为这可能引入更严重的透明排序和遮挡问题。
交互涟漪系统
交互系统采用局部捕获方案:
- 交互对象产生水平朝向的涟漪粒子;
- 粒子只存在于专用 Interaction Layer;
- 主相机不直接渲染该 Layer;
- 一台向下看的正交相机只渲染该 Layer;
- 正交相机将结果写入单通道或适当格式的 RenderTexture;
- 捕获相机通常跟随主要交互对象或活动区域;
- 脚本向水面 Shader 提供纹理、捕获中心和正交范围;
- 水面根据世界坐标还原交互纹理 UV。
粒子的扩张曲线、生命周期和透明度曲线共同定义涟漪动画。优先利用粒子生命周期表达“扩散和消散”,不要在水面 Shader 中维护逐涟漪对象列表。
第一版只需可靠支持一个局部捕获区域。多人、多水域、超大世界或多个同时活动区域应作为后续架构扩展,不要提前复杂化。
推荐实施顺序
每个阶段都必须在 Game View 中验证后再进入下一阶段:
- 基础透明水面:确认材质、透明排序、灯光和基础颜色正常;
- 深度输入可视化:先把深度差作为灰度输出,确认方向和范围;
- 深浅水颜色:只实现颜色渐变;
- 交界泡沫:先做稳定轮廓,再加入噪声;
- 伪折射:以非常低的偏移强度开始;
- 表面噪声与法线:建立连续的水面运动;
- 交互 RenderTexture:先直接显示纹理,再投影到水面;
- 涟漪合成:分别接入颜色、Emission、折射或法线;
- 材质调参与性能整理;
- 在目标场景、目标摄像机和目标平台验证。
如果某阶段出现问题,回到该阶段的灰度遮罩或原始纹理进行诊断,不要在最终颜色输出上猜测原因。
材质参数设计
向材质 Inspector 暴露的参数应按职责分组,并使用美术可理解的名称。至少考虑:
- Shallow Color / Deep Color;
- Depth Range;
- Water Alpha;
- Foam Color / Width / Cutoff / Softness;
- Foam Noise Scale / Speed / Strength;
- Refraction Strength;
- Surface Noise Scale / Speed;
- Normal Strength;
- Ripple Color / Cutoff / Intensity;
- Ripple Refraction / Normal / Emission Strength。
脚本设置的全局属性不要暴露为普通材质调参项。脚本与 Shader 的 Reference 名必须集中定义并保持一致,避免散落的字符串。
参数范围应保守,默认材质必须在未调节时就保持可用,不要把极端值设为默认值。
ASE 图的可维护性
- 优先从左到右组织数据流;
- 每个视觉模块使用独立 Comment 区域;
- 重复且稳定的逻辑可提取为 ASE Shader Function;
- 只在确实复用时抽取函数,不要为每几个节点创建函数;
- 属性名称、Inspector 名和 Shader Reference 名要区分清楚;
- 避免交叉长线;必要时使用 Relay;
- 对重要遮罩保留可视化调试路径;
- 不要手工编辑 ASE 生成的 Shader 代码作为长期方案;
- 不要依赖 Unity 6 或新版 Shader Graph 专属节点;
- 修改已有 ASE 图前先备份或使用版本控制,并保留用户已有的布局和注释。
性能原则
第一版优先正确性,但不能忽略以下成本:
- Depth Texture 和 Opaque Texture 都有带宽成本;
- 额外正交相机会增加一次局部场景渲染;
- RenderTexture 分辨率从 512 开始评估,只有画质确实需要时才使用 1024;
- 交互相机只能渲染专用 Layer;
- 根据项目需求限制相机更新、捕获范围和启用时机;
- 避免在水面 Shader 中堆叠过多高频纹理采样;
- 面向移动平台时,优先减少纹理采样、屏幕纹理读取和透明覆盖面积;
- 不要为了轻微视觉改善引入无法证明价值的额外全屏或自定义渲染通道。
任何性能优化都应基于目标平台上的 Profiler 或 Frame Debugger 证据,而不是仅凭节点数量判断。
验收标准
完成的实现至少应满足:
- 在 Unity 2022.3 LTS 当前项目中无 Shader 编译错误;
- 在 Game View 和实际运行中表现一致;
- 水深颜色随水面到不透明场景几何体的深度差稳定变化;
- 岸边和穿过水面的不透明物体附近出现可控泡沫;
- 折射不会在默认参数下产生明显画面撕裂;
- 角色移动后产生可识别的扩散涟漪,并能自然衰减;
- 主相机不会直接看见用于交互捕获的粒子;
- 交互效果在捕获区域移动时不会明显漂移;
- 材质参数分组清楚,默认值可直接使用;
- Scene、Prefab、Material、RenderTexture 和脚本引用完整;
- Console 中没有新增错误或持续警告;
- 提供简短说明,列出安装位置、必要 URP 设置、使用方法、已知限制和性能成本。
工作与沟通规则
- 每次只推进一个可验证阶段,并简要说明结果;
- 对不确定的 ASE、URP 或版本行为,先查项目实际版本和官方资料;
- 修改前先检查现有实现,不要覆盖用户资产;
- 不删除或移动无关资产;
- 不做未经请求的包升级、渲染管线迁移或项目级质量设置重构;
- 发现透明排序、平台兼容性或渲染路径限制时,明确区分“视觉近似”“当前限制”和“可选高级方案”;
- 交付时说明实际完成内容、验证方式、剩余限制和下一步建议。