《哈迪斯1》里最让我着迷的风格化渲染对象,不是那些刀光剑影的技能特效,而是整条冥河。作为一个经常和Unity CG Shader打交道的TA,我第一次看到那片深蓝紫的流体时,脑子里冒出的问题特别直接:如果只给我一个Plane和一段UV,我要怎么用Shader复刻出这种暗底亮线的流动感?后来我花了两个版本迭代,把这条河从“动态贴图”逐步调到了“接近原版气质”的程度。这篇博文就是一次完整复盘,包含视觉拆解、代码实现、以及我在工程落地时踩过的那些坑。想搞风格化流体、想做河流渲染、或者单纯想理解Unity CG Shader里UV流动和噪波扭曲怎么组合,都可以参考这套思路。
1. 冥河视觉拆解:先把一张会流动的插画翻译成参数
1.1 从截图里提取颜色分区
《哈迪斯1》的冥河并不是写实流体,更像是一张被赋予生命的高饱和插画。我把它放大看了很多遍,发现颜色其实可以拆成三个层次:最底层的深蓝黑和紫褐色负责给画面压住重量感,中层的青蓝和淡紫负责表现流体的体积,最上层的白色和亮青色细线则承担了轮廓和视觉引导。这三层之间的关系非常明确:暗的地方足够暗,亮的地方足够亮,中间几乎没有复杂的过渡。做风格化渲染最忌讳的就是把颜色调成连续的渐变,看起来像塑料,原版的处理方式是刻意保持明暗跳变。
落到Shader参数上,我最终保留了三个Color属性:_DeepColor(基底暗色)、_MidColor(中层主色)、_GlowColor(高亮描边色)。这三个颜色在运行时并非均匀混合,而是依靠贴图alpha、噪波强度和视角边缘同时参与计算,不同区域会呈现完全不同的色调权重。这样做的目的是让河面看起来有“信息层次”,而不是一个简单的大色块。
1.2 看懂流动形态:螺旋、带状与颗粒的共存关系
除了颜色,《哈迪斯1》的冥河在形态上有一个很重要的设计,就是同时存在三种不同尺度的运动。第一种是大尺度的带状流动,像绸缎被风吹动一样,整条河流有明显的主方向;第二种是中尺度的螺旋涡流,尤其在河面拐弯处和狭窄处,会出现局部回旋;第三种是小尺度的颗粒闪光,像碎星一样漂浮在河面上,逐帧闪烁。
这三层运动在Shader里对应完全不同的技术手段。带状流动我用了最简单的主纹理UV滚动;螺旋涡流用了局部旋转UV加上遮罩;颗粒闪光则是把一张高频噪声贴图叠加到漫反射和高光通道里,让它随时间抖动。三层速率必须拉开差距,否则会糊成一团。原版给我的体感是:主流动速度偏慢,涡流中等,高光颗粒最快,但高光颗粒的透明度又很低,属于“存在但不抢戏”的级别。
1.3 动态强度要服务于游戏阅读性
很多人在复刻这种效果时会犯同一个错误:把水面做得太花。我记得第一版Shader把流速调到很高,涡流强度也特别大,结果放进实际关卡里,玩家完全读不清地形,角色的轮廓也被水流干扰了。后来我把动态强度整体降到60%左右,再配合角色脚下的“跟随波光”粒子,游戏性反而好了很多。
这条经验我想放在最前面说:风格化场景的特效不是越强越好,而是要跟玩法形成一个动态对比。在《哈迪斯1》这种俯视角地下牢关卡里,水面既是视觉主体,也是陷阱和通行区域。它的流动必须能暗示方向,但不能覆盖怪物攻击和玩家操作的信息。所以后面所有参数的调节,我都围绕一个原则:让水面在静态截图上好看,在动态游玩中安静。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型与资产准备:为什么是UV Flow而不是粒子系统
2.1 大面积水面用粒子系统是灾难
我最初也考虑过用粒子+Trail来做冥河,因为原版很多细碎的涡流看起来特别像粒子层。但粒子方案在实操中很快就被否掉了:要覆盖一整片关卡地图,需要几千个粒子,排序混乱、Overdraw高、不同分辨率下分布还不可控。更麻烦的是,粒子的运动无法跟场景网格的UV保持连续,一旦边缘不齐就会露出非常明显的穿帮。
UV Flow方案的优势正好相反:性能开销主要来自片元着色器,场景有多大就采样多少片元,开销完全可控;流动方向通过UV速度控制,和地形网格自然贴合;更关键的是,它可以跟顶点色、世界坐标遮罩这些信息自由组合,做出河流中间快、岸边慢的渐变效果。粒子适合做点缀,大范围流体一定要用Mesh + Shader。
2.2 网格与UV的规划直接决定效果上限
这条河的网格我用的是最简单的Plane改。网格尺寸按照关卡地形切成长条形,宽度大概8到12米,长度直接拉伸到几十米。Plane本身不需要太多细分,但要留意UV的V方向不能跟着模型拉伸得过于夸张,否则岸边波纹会被放大成一条条横线。我习惯把UV做两套:一套是模型自带的常规UV,保留了0到1的横纵向比例;另一套是通过脚本或顶点色生成的沿河岸长度方向递增的UV,专门给流动纹理使用。
如果你只是用小尺寸Plane平铺,那V方向的波纹会随着平铺次数反复出现,接缝处特别显眼。推荐的做法是:让材质主纹理Tiling的X方向保持较高值,Y方向保持1左右,配合Wrap Mode设为Repeat,这样纵向波纹会被压扁,横向上反而会出现连绵不断的长条纹路,更接近原版绸带感。
2.3 两张程序化贴图就能拿下大部分资产
很多项目的风格化河流喜欢用FlowMap,但《哈迪斯1》的冥河并不需要严格的FlowMap方向引导,它更像“大体方向一致,局部有扰动”,所以只用两张平铺噪声贴图就够用:一张做主纹理,一张做扰动和颗粒。
主纹理我推荐用1024x512的尺寸,绘制方法可以很简单:在Photoshop里新建文档,用柔边圆画笔横向拉出一些长条曲线,低透明度叠加,然后在通道面板里把R通道和高光细节分开——R通道用来控制流动遮罩,A通道用来控制河流边缘透明度。如果你想做得更可控,还可以再叠加一点细微噪点作为河面颗粒。
噪波纹理可以在Photoshop里用“渲染->纤维”加“极坐标”生成,也可以用网上现成的Perlin Noise无缝贴图。关键是它必须Tileable,而且不能有明显的十字接缝。我自己最终用的是128x128Perlin噪声,R通道和G通道采样结果错开,分别用于大尺度扰动和小尺度闪烁。两张贴图加一个网格体,就能把河流的主干撑起来。
2.4 为什么用Unity CG Shader而不是URP Shader Graph
这里需要特别声明一下:标题里提到的UnityCG
