《鸣潮》UE4多平台效果与性能优化实践

[UFSH2023]《鸣潮》基于虚幻引擎4的多平台效果和性能优化实践 | 王宏波 库洛游戏

TAAU 方案解析

0. 背景与核心挑战

  • 项目类型: 开放世界、二次元(NPR)、ACT战斗、怪物收集。

  • 核心挑战:

    • 多平台适配: 需兼顾高画质PC端和性能受限的移动端。

    • 二次元特性: 大量高频边缘(勾边、风格化草/树),对抗锯齿要求极高。

    • 动态光源: 同屏动态光源极多(200+,夜晚更多),远超常规手游。

1. 渲染管线选择:为何坚持 Deferred (延迟渲染)?

在移动端,通常因带宽限制首选 Forward 或 Forward+,但《鸣潮》选择了 Deferred Rendering

  • 决策依据:

    1. 光源数量: 需支持同屏数百个动态光源,Deferred 在多光源下性能更优。

    2. 效果追求: 需要在手机上实现高级效果,如 SSR (屏幕空间反射) 和 GTAO (地面实况环境光遮蔽),Deferred 的 G-Buffer 提供了必要数据。

    3. 开发成本: 对团队而言,Deferred 与 Forward+ 的开发成本差异不大。

  • 代价: 无法使用 MSAA,必须依赖后处理抗锯齿(Post-Process AA),这给二次元画面的边缘处理带来了巨大挑战。

2. 二次元游戏的抗锯齿挑战

  • 边缘像素占比高:

    • 写实 PBR 游戏:同屏边缘像素占比约 1% - 2%。

    • 二次元 NPR 游戏:由于勾边(Outline)和风格化植被,边缘占比高达 4% - 5% 甚至更多。

  • 现象: 锯齿(Aliasing)和高光闪烁(Flickering)比写实游戏更严重,普通的 TAA 容易糊或闪。

3. TAA (时间性抗锯齿) 深度优化

《鸣潮》采用了一套混合定制的 TAA 方案,核心在于平衡鬼影(Ghosting)闪烁(Flickering)

3.1 渲染流程调整

  • 位置后移: 将 TAA Pass 从默认位置移到了 BloomToneMapping 之后。

    • 注:虽然 Bloom 可能会放大闪烁,但综合考虑后仍选择此顺序(因为性能原因)。
  • 定制 Velocity Pass: 增加了专门的 Velocity Buffer (速度缓冲) 用于计算动态物体的历史回溯。

3.2 鬼影优化 (Ghosting)

核心是历史像素混合(History Clamping)的精度与性能权衡。

  • 采样优化 (Mobile):

    • PC端通常用 9点采样。

    • 移动端优化为 十字星 5点采样 (5-tap cross),节省带宽。

  • 包围盒 (Clamping Box):

    • 移动端选择最廉价的 AABB (轴对齐包围盒) 来限制历史像素颜色范围。
  • 颜色空间选择:

    • YCoCg 空间: 高配机型使用,利用亮度(Y)做 Clamp 更符合人眼感知,效果更好。

    • RGB 空间: 低配机型使用,省去色彩空间转换开销,降低 5-tap 采样的带宽压力。

3.3 角色勾边的特殊难题 (The "Outline" Problem)

这是二次元游戏特有的性能痛点。

  • 问题根源:

    • 为了消除角色运动时的鬼影,需要精确的 Velocity Buffer。

    • 但渲染角色的代价极高(Base Pass x2, Velocity x2, Shadow, Skinning x2等)。

    • 性能妥协: 为了省性能,移动端去掉了角色勾边(Outline)的 Velocity 渲染

  • 引发新问题: 勾边没有速度信息,无法正确回溯历史帧,导致严重的边缘闪烁(头发、服饰边缘)。

  • 解决方案 (混合策略):

    1. 低通滤波 (Low-Pass Filter): 对判定为闪烁的边缘区域进行简单的模糊处理(利用已有的 5-tap 采样数据),压制闪烁。

    2. 动静分离权重: 引入两套权重系统。

      • 速度越快 当前帧权重越高(减少鬼影,但可能增加闪烁)。

      • 速度越慢 历史帧权重越高(画面更稳定)。

    3. 动态锐化: 针对被 TAA 模糊的动态物体,使用 Unsharp Mask 进行局部锐化(同样复用 5-tap 数据)。

4. TAAU (时间性超级分辨率)

在 TAA 基础上实现的 Upscaling(上采样)方案。

  • 算法实现:

    • 基础:基于目标像素到源像素距离的权重插值。

    • 进阶:实现了类似 FSR 1.0 的多项式逼近(Polynomial Approximation)算法,考虑边缘信息,效果优于简单双线性。

  • 分级策略: 低配用简单的双线性或基础 TAAU,高配开启更复杂的边缘重建算法。

5. 性能参考数据

测试机型:骁龙 865

  • 仅开启 TAA: ~1.1 ms

  • 开启 TAAU (Upscaling): ~1.5 ms


总结核心思路: 《鸣潮》的图形优化是在追求“主机级特性”(Deferred管线、复杂TAA)和“移动端限制”之间做极致的工程权衡(Trade-off)。例如,为了性能放弃了完美的 Velocity Buffer,再通过后处理算法(低通滤波、动态权重)去弥补由此产生的画质缺陷。


One Pass Deferred 管线避坑指南

0. One Pass Deferred 管线概述

  • 核心目标: 将所有主要的渲染Pass合并到一个 Render Pass 中,利用移动端 GPU 的 On-Chip Memory (片上内存),减少对系统内存的读写带宽消耗。

  • 基础实现:

    • API 支持: OpenGL ES 3.2, Vulkan, Metal 2/3。

    • G-Buffer 布局 (初始版): 3张 G-Buffer (RGBA8) + 1张 SceneColor + 1张 DepthBuffer。共计4张RT + 1张Depth。

    • 材质分类: 卡通角色(NPR)、风格化植被(NPR)、PBR场景。通过 Stencil Mask 区分。

    • 深度获取: 依赖 Depth Fetch (从深度缓冲读取深度信息)。

1. 巨坑一:ARM Mali GPU 上 Depth Fetch 导致 LPK 失效

这是移动端延迟渲染最常见且最严重的性能陷阱之一。

  • 现象:

    • 在高通骁龙和苹果设备上性能正常。

    • ARM Mali GPU 上,三个 Lighting Pass 的 GPU 指令周期极高,性能骤降。

  • 原因分析 (Streamline 分析):

    • LPK (Late-Z Pass Kill) 失效: Mali GPU 的一种重要优化机制,用于提前剔除被遮挡的像素。

    • 罪魁祸首: Depth Fetch。在 Mali GPU 上,任何形式的深度纹理采样(无论在 One Pass 还是其他 Pass 中)都会导致当前 Pass 的 LPK 优化彻底失效。

  • 数据对比:

    • 关闭 Depth Fetch: LPK 剔除像素量 ~1.2 M/帧。

    • 开启 Depth Fetch: LPK 剔除像素量 ~0.01 M/帧 (几乎为零,性能暴跌100多倍)。

    • 注:ARM 表示最新的 Immortalis-G720 可能已在驱动层面解决此问题,但旧设备仍受影响。

1.1 解决方案:混合管线重构 (Hybrid Pipeline)

为了在 Mali 上保持高性能且不降低画质,团队选择了艰难的重构之路。

  • 核心冲突:

    • 必须放弃 Depth Fetch 以恢复 LPK。

    • 放弃 Depth Fetch 意味着必须把深度信息存入 G-Buffer。

    • PLS (Pixel Local Storage) 限制: 移动端片上内存通常只有 128-bit (尽管文档可能写更高,实际可用往往受限)。原有的 G-Buffer 布局已经占满,无法再塞入深度信息。

  • 最终方案: One Pass Deferred + Forward (Hybrid)

    1. 角色改为 Forward 渲染: 将最复杂的卡通角色从 Deferred 管线中剥离,走前向渲染。

    2. G-Buffer 重编码:

      • 因为角色移出,G-Buffer 不再需要存储角色特有的数据。

      • 利用腾出的空间,将 线性深度 (Linear Depth) 编码进 G-Buffer。

    3. Pass 结构调整:

      • 初版尝试失败: 若将角色 Forward Pass 放在透明物体渲染之后,会导致排序错误、效果缺失(水体、雾效等),且打断 One Pass,增加带宽。

      • 最终成功架构: 将角色 Forward Pass 紧接在 Lighting Pass 之后,在同一 Render Pass 内完成。这样只需额外处理 Decal 和 Light Function,而水体、雾等可在后续统一处理。

  • 优化成果 (Mali GPU):

    • 平均温度下降 5-6°C

    • GPU 时钟频率下降约 25%

2. 小坑二:UE4 引擎 Bug 导致带宽节省不达预期

这个问题隐藏较深,主要影响高通 Adreno GPU。

  • 现象:

    • 理论上 One Pass 应该大幅节省读写带宽。

    • 实际上,读带宽 (Read Bandwidth) 节省明显,但 写带宽 (Write Bandwidth) 几乎没有变化。

  • 原因分析:

    • UE 4.26/4.27 RHI Bug: 引擎底层的 Render Hardware Interface 实现有缺陷。

    • 在结束 Render Pass 时,应该 Discard (丢弃) 掉中间计算用的 G-Buffer,不写回系统内存。

    • 但有 Bug 的代码仅对 SceneColor 和 Depth 生效,而忽略了 G-Buffer RT A/B/C,导致它们仍然被强制写回了内存,浪费了大量带宽。

    • 注:UE5 已修复此问题。

  • 修复: 修改引擎底层代码,确保所有中间 RT 都能被正确 Discard。

3. 带宽优化最终数据

  • 测试结果 (60fps):

    • 理论预期节省: ~1.8 GB/s

    • 实际节省: ~830 MB/s

  • 原因: 现代移动 GPU (Adreno/Mali) 都有非常高效的 AFBC (ARM Frame Buffer Compression) 或类似技术,本身的带宽压缩效率已经很高,因此 One Pass 带来的额外收益比理论值小。

  • 各平台表现:

    • 读带宽节省: > 30%

    • 写带宽节省: 10% - 15%

  • 最终带宽消耗: 约 1.2GB/s - 1.4GB/s (对于 60fps 的高画质游戏来说非常优秀)。


总结核心思路: 移动端 Deferred 管线的成功关键在于对硬件特性的极致利用与规避。必须了解 Mali 的 LPK 机制和 PLS 大小限制,同时要敢于修改引擎底层 RHI 以修复阻碍优化的 Bug。混合管线(Hybrid Pipeline)是平衡复杂材质需求与硬件限制的有效策略。


多平台植被渲染方案

0. 多平台适配策略

《鸣潮》采用了一种统一化的多平台适配框架,将不同平台视为同一连续谱系上的不同配置点。

  • 核心理念:

    • PC高配 PS5

    • PC中配 PC低配 PS4 移动端高配

    • 影响因素: 计算能力 (CPU/GPU)、内存、IO性能、功耗、包体大小。

  • 适配阶段:

    1. 打包时: 区分平台资源,烘焙特定数据(如Shader变体、纹理格式)。

    2. 加载时: 按需加载,过滤掉非当前平台所需的数据。

    3. 运行时: 动态调整画质参数(如LOD距离、分辨率缩放)。

  • 重要提示 (坑):

    • Gameplay数据必须与渲染数据分离: 碰撞、寻路、物理等数据不能随画质LOD变化,否则会导致角色陷地、穿墙等严重Bug。

    • 优势: 作为ACT游戏,只需关注角色周围30-50米的Gameplay精度,远距离物理精度要求低(对比FPS游戏)。

1. 植被渲染方案总览

针对开放世界大规模森林,采用了分级的渲染策略。

平台近景 (Close)中景 (Middle)远景 (Far)
PC / 主机模型树 (Mesh Tree)Billboard树Imposter树
移动端Billboard树Imposter树Imposter树

2. Billboard 树 (广告牌树)

作为移动端近景和PC中景的主力方案,旨在替代传统的插片树模型。

这里的Billboard 树指的是RTR4 13.6.5小节 Billboard Representation提到的Billboard Cloud方法。

  • 实现原理: 将原本复杂的插片树叶,替换为多层面朝相机的 Billboard 面片。

  • 优势:

    • 面数大幅降低: 仅需原模型树面数的 30% - 40%

    • 效果还原度高: 在视觉上能基本还原插片树的体积感和光影。

  • 缺陷与解决:

    • 问题: 阴影会随相机转动而错误旋转(因为Billboard面朝相机)。

    • 解决: 渲染阴影时,让 Billboard 面朝光源,而非相机。

3. Imposter 树 (基于图像的代理树)

用于极远景的高效渲染方案。

  • 核心概念: 并非简单的Billboard。是在离线阶段,围绕树木从多个角度拍摄一系列“快照”,存储其渲染信息。运行时根据相机视角,选取最接近的快照进行合成渲染。

  • 设计目标:

    • 还原着色与形态。

    • 全功能投影支持: 自身投影、接受场景投影、云层投影。

    • 极低的内存与Draw Call占用。

  • G-Buffer 设计 (32-bit Texture):

    • RG: 法线 (Normal) 信息。

    • B: 局部深度偏移 (Local Depth Offset)。

    • A: Diffuse灰度 + 材质标记 (区分树叶/树干,用于不同着色处理)。

  • 深度还原技术 (核心):

    • 利用存储的 Local Depth Offset 和 Billboard 在相机空间的位置,重建出近似原始模型的深度信息。

    • 有了准确深度,就能完美支持各类阴影技术 (Shadow Map, AO, 雾效等),与普通模型无异。

  • 内存优化:

    • 动态 Texture Array: 扩展UE默认机制,支持按需流式加载 (Streaming) Imposter 切片,大幅降低显存占用。

    • 数据: 3000+ 棵树实例 (50种类型),仅占用 < 15MB 内存。

  • 性能表现:

    • 1000+ 棵可视树木,仅需 4个 Draw Call

    • 总面数 < 4万。

    • GPU耗时极低。

4. 其他工程优化

  • LOD 集成: Billboard 和 Imposter 直接嵌入树木的 LOD 链中,引擎自动处理切换。

  • ISM (Instanced Static Mesh) 优化: 针对使用 ISM 的近景树木,选取 Chunk 中最大的物体来计算 LOD 切换距离,解决 ISM 包围盒过大导致 LOD 切换迟钝的问题。


总结核心思路: 《鸣潮》通过定制化的 Billboard 和 Imposter 技术,成功在移动端实现了大规模植被的低成本渲染,同时保持了动态光影(特别是阴影)的完整性,是其能够在移动端呈现开放世界大场景的关键技术之一。