[UFSH2023]《三角洲行动》端手一体地形渲染方案

[UFSH2023]揭秘《三角洲行动》如何在虚幻引擎4中实现先进的端手一体地形渲染方案 | 徐云翰 腾讯天美Y工作室

《三角洲行动》端手一体地形渲染方案


项目背景与目标

项目定位

  • 三角洲行动 是一款 写实风格大世界 FPS 游戏,由腾讯天美 Y1 工作室(原金山工作室)研发
  • 核心理念:端手一体(Cross-Platform)——不同于"端游出 HD 版手游"的做法,而是:
    • 端游 对标 3A 品质
    • 手游 追求次世代品质
    • 使用 同一个引擎(UE4),同一套关卡和美术资产,同时进行双端开发
    • 目标:一次生产,端手同步,美术无需为端游和手游独立制作资源

地形技术目标

一句话总结:让手游拥有端游级的品质

  • 基本逻辑:先把品质追到最高,再用各种技术突破让它落地到手游
  • 同时完善美术工具链,使美术可以稳定产出场景内容

手游地形已达成的成果

指标具体数据
大世界规模10km 级别
材质层数全场景支持 32 种材质(可扩展至 256 种,性能不受影响)
材质精度每米 500+ texels(对比 CODM 的 256 texels/米,高出一倍)
特色功能峭壁优化、海量贴花、移动端 Tessellation、湿度/颜色等生态信息变化
性能表现三角洲高配在帧率、发热、带宽上甚至优于 CODM 低配
  • 以上多项特性在手游上均属 首创

基本方案:地形材质与混合

地形渲染的核心问题归结为两块:材质(Material)和 混合(Blending)。

原生方案:传统权重图方案(Splat Map)

工作原理

  • 每层材质对应一个 权重通道(Weight Channel)
  • 多层材质的权重存储在 权重图(Splat Map)中,例如 2 层材质使用一张纹理的 RG 通道
  • Pixel Shader 中采样权重图,获取每层材质权重,按权重混合各层纹理

优点

  • 四层以下材质时计算简单,效果可控

问题(以 8 层材质为例)

  • 时间开销:每个像素需要 18 次纹理采样,非常昂贵
  • 空间开销:需要 两张 RGBA 权重图,即使压缩后内存占用依然很大
  • 可扩展性极差:材质数量增加时,时间和空间开销 成倍增长
    • 项目用了 32 层 → 开销是 8 层的 4 倍

UE4 原生优化方式

  • 地块(Component) 划分材质变体,只采样该地块实际用到的材质
  • 但存在问题
    • 不同地块材质不同 → 影响合批(Batch)
    • 制作不可控、灵活度不够 → 限制美术发挥,影响最终品质

核心矛盾

真正的需求是 整个大世界支持更多材质,而不是每一个像素都需要那么多材质层。这就是新方案的突破口。


业界参考方案:Ghost Recon(幽灵行动)的 Material ID 方案

工作原理

  1. 用一张 Texture Array 存放所有材质的纹理
  2. 用一张 Material ID 图 覆盖整个地形,每个元素对应 1 米 的地形格子,存储该区域使用的 材质 ID(即 Texture Array Index)
  3. 在 PS 中以 正方形 为单位,采样周围 4 个 ID,再从 Texture Array 采样对应纹理
  4. 根据 距离 将四种材质做 线性混合

问题

  1. 没有权重信息:权重是 非零即一 的,只能标记某 1 米区域是否有某材质,美术 无法控制混合程度
  2. Block 问题(方格化伪影):材质边缘出现明显的 锯齿感 / 阶梯感,尤其在曲线边界处非常明显

三角洲行动的自研方案:ID 图 + 权重 + 三角形混合

三大核心改进

改进点具体做法
① 保留权重同样使用 ID 图,但 保留了权重信息,美术可以精确控制混合程度
② 三角形单位三角形(而非正方形)为混合单位 → 减少采样次数 + 大幅缓解 Block 问题
③ 每米最多 3 种材质全场景支持 32 种材质,但保证 每米局部最多使用 3 种材质

PS 中的工作流程

  1. 采样 3 个 Texel(三角形的 3 个顶点)
  2. 得到 6 个材质 ID
  3. 筛选出 3 个 最终参与混合的材质
  4. Texture Array 最多只需采样 3 次

性能优势

  • 由于每米最多 3 种材质,Texture Array 采样次数上限为 3 次(对比原生方案的 18 次采样)
  • 每米 3 种材质对美术来说也 完全够用

与主流方案的对比

维度原生 Splat MapGhost Recon ID 图三角洲自研方案
性能差(采样多)中等好(最多 3 次采样)
内存大(多张权重图)较小
效果好(有权重)差(无权重 + Block)好(有权重 + 三角形混合)
可扩展性极差(线性增长)中等极好(材质数翻倍无额外开销)

一句话总结:以更高的性能,实现了更好的效果。


关键概念速查

  • Splat Map(权重图):传统地形方案中存储每层材质权重的纹理,每个通道对应一层材质
  • Texture Array:将多张同尺寸纹理打包成数组,通过索引访问,避免绑定多张独立纹理的开销
  • Material ID 图:每个 texel 存储对应地形区域使用的材质索引,而非权重值
  • Block 问题(方格化伪影):以正方形网格为单位切换材质导致的边缘阶梯状锯齿
  • 每米 Texel 数:衡量地形材质精度的指标,数值越高细节越丰富(三角洲行动手游达到 500+ texels/m)

Adaptive Dynamic Texture Array:32 层材质的内存优化


问题:32 层材质的内存爆炸

  • 前面已实现 32 层以上材质方案,但 32 层纹理 × 2(至少 BaseColor + Normal)= 内存爆炸
  • 如果削减材质数量 → 品质降低(一般手游只有 4~8 层
  • 传统的基于 Mipmap 的 Texture Streaming 技术 无法用于 Texture Array(Texture Array 是整体对象,不能对单层做独立 Streaming)

解决方案:Adaptive Dynamic Texture Array

核心思路

同一时间,屏幕上只会用到 32 种材质中的一部分

  • 在 GPU 内存中 只存放当前视野内用到的材质纹理
  • 当玩家移动到新区域 → 需要的材质发生变化 → 动态更新 Texture Array 内容
  • Texture Array 也会自动 Resize → 所以叫 "Adaptive"

内存优化效果

对比项数据
原始 32 层全加载~85 MB
优化后(动态 8 层)~21 MB
压缩比仅原来的 25%

如何控制每个区域的材质层数

  • 使用 PCG(程序化内容生成) 整体规划不同区域用到的材质种类和数量
  • 提供 自动化 + 可视化的层数检查工具
  • 过渡区 / 野外非 POI 区域,内存压力较小 → 适当放开限制,提高野外品质

技术落地的工程思路

不只是技术实现,而是一个 完整的规划链条

  1. 方案设计 → 确定技术路线
  2. 与美术 / TA 协同 → 规划不同生态、不同区域的材质层数
  3. 与客户端评估 → 评估不同区域的内存压力
  4. 技术实现 → 最终找到 内存与品质的最佳平衡点
  • 例如"为什么是 8 层而非 7 层或 9 层",都是 前期充分评估 的结果

材质混合算法:改进的高度混合


传统混合方式对比

权重混合(Weight Blending)

  • 最基础的方式:根据 权重值线性插值 两种材质
  • 效果较 平淡,过渡区看起来"糊"在一起

高度混合(Height Blending)

  • 根据材质纹理的 高度信息(Height Map)决定混合方式
  • 效果更加 物理真实:例如泥土和石块的混合,石块会自然地"凸出来"
  • 缺点:传统高度混合算法 计算复杂(需要获取每层高度 → 求和 → 算平均高度等)

三角洲行动的新高度混合算法

核心优势

  • 计算极其简单:只需要几次乘法操作
  • 支持权重控制:不同权重下都能产生良好的高度混合效果
  • 两个美术可调参数
    • Scale :控制高度混合的幅度
    • Sharpness :控制混合边界的锐利程度
  • 32 层材质中每一层的这两个参数都可以独立设置,自由度极高

远近自适应:统一的混合公式

问题

  • 高度混合在 近景 效果优秀
  • 但在 远景 会出现 方格化伪影(Block Artifact),此时权重混合反而更好

解决方案

  • 在公式中引入 系数
  • ,且 时 → 公式 完全退化为权重混合
  • 通过 距离 控制 的值:
    • 近处 较大 → 高度混合
    • 远处 趋近于 0 → 权重混合
  • 过渡 非常平滑,无需额外的分支或判断

一个统一的公式,同时实现近处高度混合 + 远处权重混合 + 平滑过渡,且消耗极低。


CDLOD + VT Render 系统:地形渲染管线重构


Virtual Texture(VT)基础回顾

VT 的出发点

  • 假设有一张 超大超高分辨率纹理 平铺在整个地形上
  • 所有材质的混合结果都 预先烘焙 在这张纹理中
  • Base Pass 中只需 一次采样 即可 → 无需实时做材质混合
  • 但这张纹理可能有 上百 TB,无法直接存储

运行时生成 + 缓存

  • 运行时按需生成 这张超大纹理中 当前用到的部分
  • 这张超大纹理 = 虚拟纹理(Virtual Texture, VT)
  • 生成的基本单元 = Page(页)
  • 在 Base Pass 之前有一个 VT Pass,负责生成 VT Page

VT 的核心优势

  • 将逐帧的采样和混合计算,均摊到多帧中执行
  • 结果缓存后,Base Pass 只需 一次采样
  • 大幅优化 性能、带宽、发热

UE4 原生地形方案的问题

Landscape Proxy 架构

UE4 原生地形使用 Landscape Proxy 作为核心数据结构:

  • 地形被网格切割(如 100m × 100m 一格),每格 = 一个 Proxy
  • 10km 大世界 → 上千个 Proxy,对应上千个关卡(Level)

具体问题

问题类别具体描述
内存浪费Proxy 存储了大量冗余数据(草权重图、高度图等),在自研方案下用不到
加载缓慢Proxy 体积大 → 加载慢 → 上千个 Proxy 即使远处用 Mesh 替代也会 严重卡顿
Draw Call 爆炸Base Pass 中产生 大量 Draw Call,且 无法 Instance
数据管理不便物理数据和渲染数据耦合在一起:服务端不需要渲染数据、客户端希望统一管理物理(不仅限地形)、物理和渲染的加载距离不同……

自研方案:CDLOD + VT Renderer

整体架构对比

PassUE4 原生三角洲行动自研
Base PassLandscape ProxyCDLOD
VT PassLandscape ProxyVT Renderer

两个 Pass 都完全抛弃了 Landscape Proxy,从零开发

CDLOD(负责 Base Pass)

CDLOD (Continuous Distance-Dependent Level of Detail):

  • 1~2 个 Draw Call 即可绘制 整个地形 → 解决 Draw Call 爆炸问题
  • LOD 切换无接缝
  • 可以 非常自由地控制面数,在高 / 中 / 低配下都能达到性能与效果的平衡

VT Renderer(负责 VT Pass)

  • VT Renderer 是一个极度轻量化的数据结构
  • 只包含两样东西:
    1. Material ID 图(前面自研的材质 ID 纹理)
    2. 一个极简 Mesh(只有 2 个三角形的平面片)
  • 只做一件事:在 VT Pass 的 Fragment Shader 中生成 VT Page

收益总结

  • 一举解决 内存浪费和加载卡顿问题
  • 拥有自己的数据结构 → 为后续 大刀阔斧的优化和修改打下基础
  • 感谢 UE4 打下的强大基础架构,使得自研方案能够方便地落地

地形品质进阶:四大提升手段


生态变化(Ecological Variation)——不增加材质数量的丰富度提升

核心思路

  • 已有 32 种材质,在手游上已是极限数量
  • 目标:不增加材质数量,但继续提升场景丰富度
  • 答案是 "变化"
    • 颜色变化(Color Tint)
    • 湿度变化(Wetness)
    • 明暗变化(AO / Brightness)
  • 例如:同一种地面材质,通过 染色 给出不同区域的颜色差异,美术自由度极高

实现方式:全场景信息图

  • 将变化信息存储在 一张覆盖全场景的纹理 上(如颜色图、湿度图)
  • 精度要求:每米一个信息(1 texel/m)
  • 问题:10km 大世界 → 10K × 10K 纹理 → 压缩后仍需 ~133 MB,手游不可接受

技术突破:移动端 Clip Map 技术

核心观察

超大纹理上,同时用到的区域可能连 1% 都不到——越高精度的 Mip Level,只有玩家附近很小范围才用得到

工作原理

  • 类似 Mipmap 的空间局部性 思想
  • 原始大纹理的每个 Mip Level,只在内存中存放当前可见的区域(绿色区域)
  • 玩家移动时 → 滚动更新(Rolling Update)对应区域的数据

内存优化效果

项目数据
原始 10K 染色图~133 MB
使用 Clip Map 后< 2 MB
压缩比降至约 1%

已落地的生态变化效果

功能具体表现
水坑读取全场景 湿度图,结合地形纹理的 高度信息高度混合(Height Blending),水坑边缘自然
河边 / 水下湿度大范围湿度渐变
湖泊 / 积雪染色湖泊区域染色(上方再叠加湖面模型)
河道 / 峭壁变色峭壁区域的特殊颜色处理

性能分析

  • 染色采样 在 VT Pass 中进行(烘焙阶段)
  • 额外开销:几个 ALU + 一次纹理采样 → 性能几乎无影响
  • 如果放在 Base Pass 中做 → 代价较大(不推荐)

Clip Map 的通用性——不仅仅用于地形

Clip Map 本质上是一个通用的纹理 Streaming 方案

应用对象具体效果
草地同一种草(同一个 Instance 绘制)通过 Clip Map 获取不同颜色变化;草与地面衔接处通过 Clip Map 存储 AO 遮蔽 信息
树木模拟 生长年龄树叶健康度四季颜色变化 等,不增加 Draw Call
岩石、植被、河流均可使用

额外优化:Material ID 图也改用 Clip Map

  • 此前 VT Render 中的 Material ID 图 需要被 Streaming
  • 将其改为 Clip Map 形式 → 变成一张 覆盖整个场景的常驻数据
  • 好处:进一步优化卡顿(减少 Streaming 导致的帧率波动)

峭壁渲染优化(Cliff Rendering)

问题分析

表现

  • 地形峭壁(陡峭面)出现 纹理拉伸失真
  • 原因:地形默认使用 从上往下的投影(Z 轴投影)计算 UV
  • 对于近乎垂直的面 → UV 被严重拉伸 → 采样出来的纹理也被拉伸(相当于把正方形贴图拉成了长方形)

后果

  • 美术 不敢制作陡峭山体 → 手游的山普遍是 低精度的缓坡曲线
  • 但 3A 端游的野外常有 高山峭壁,做好峭壁品质会有 质的提升
  • 三角洲行动的美术设计和原画中有 大量峭壁需求

解决思路

核心原理

  • 拉伸发生在 Base Pass 的 UV
  • 用拉伸的 UV 去采样 未变化的 VT → 结果拉伸
  • 最直接的解决方案:让 VT 内容也跟着 UV 一起变化 → 用拉伸 UV 采样变化后的 VT → 结果正确

本质技术:Triplanar Mapping

  • 传统方式:只从 Z 轴(上往下)做投影算 UV
  • Triplanar Mapping:分别从 X 轴、Y 轴、Z 轴 三个方向投影,计算三组 UV,采样三次纹理,再按 法线方向权重 混合

关键改进:将 Triplanar Mapping 做进 VT 中(在 VT 烘焙阶段处理),而不是像 Farcry 那样在 Base Pass 中单独绘制峭壁(那样很贵)

三种优化方案对比

方案原理采样次数效果
Lazy Triplanar三个方向中 选权重最大的一个不增加采样明显接缝
Biplanar(二方向混合)法线分量最大的两个方向,用法线分量做权重混合多一倍采样接近 Triplanar 效果,但采样翻倍
Stochastic Blending(最终方案)类似 Farcry 的随机混合思路,通过 控制概率分布 + Alpha Test 模拟 Alpha Blending不增加采样类似 Dithering 效果,近距离贴着看才能发现瑕疵

最终选择:Stochastic Blending

  • 不增加采样数——这对手游至关重要
  • 原理:不同像素按概率选择不同投影方向,利用 Alpha Test 替代 Alpha Blend
  • 视觉效果:非零距离贴着看,完全看不出瑕疵
  • 设计哲学:

手游需要的正是这种"牺牲 1% 来换取 99% 提升"的技术

  • 这种 Stochastic 思路后续还会被复用(在其他功能中也会使用类似方法)

关键技术总结

技术核心手段关键收益
生态变化Clip Map + 全场景信息图不增加材质数,大幅提升丰富度,133MB → <2MB
峭壁优化Triplanar in VT + Stochastic Blending零额外采样开销,消除峭壁拉伸
Clip Map 通用化Material ID 图、草地、树木均可使用减少 Streaming 卡顿,统一框架

远景细节优化:SVT 法线烘焙方案


问题:远景几何细节严重丢失

现象

  • PCG 生成的 沟壑、侵蚀 等地形细节在远景中被 完全抹平
  • 近处看地形丰富多变,远处看一片光滑

根本原因

  • 编辑器中地形有 38 万面
  • 手游实际运行时(经过 LOD 简化)只剩 几万面("一个零头")
  • 越远网格密度越低 → 没有顶点 → 自然没有几何细节
  • 这是手游的硬性限制,必须降面数

VT 的构成:SVT + RVT

插入一个关键概念,理解后续方案的前提

  • 三角洲行动的 VT(Virtual Texture) 由两部分组成:
类型全称说明
RVTRuntime Virtual Texture运行时动态生成,覆盖近处高精度 Mip Level(如前 3 层)
SVTStreaming Virtual Texture离线预烘焙,覆盖远景低精度 Mip Level
  • 例如一个 16K 的 VT:
    • 前 3 层 Mip(高精度):由 RVT 运行时渲染生成
    • 后续 Mip(低精度):由 SVT 离线烘焙,运行时 Streaming 加载
  • SVT 被加载后 与 RVT 共享同一个 Page Pool不增加额外内存开销

解决方案:将顶点法线烘焙进 SVT

思路推导

  1. 暴力方案:把所有顶点法线存在一张纹理中,在 PS 中采样 → 理论上能恢复几何细节,且精度是 逐像素 的(比网格精度更高)

    • 问题:全场景法线纹理 → 内存、带宽、采样数全部爆炸
  2. 关键发现:已经有一张 覆盖全场景的纹理SVT

    • SVT 本身就有 法线通道
    • SVT 本来就会被 Streaming 进来
  3. 最终方案

    在离线烘焙 SVT 时,将高模的顶点法线(几何法线)混入 SVT 的法线通道

    • 当 SVT Streaming 进来时 → 自然带上了 逐像素精度的几何法线
    • 无需额外纹理、无需额外采样

效果

对比项数据
原始编辑器面数38 万面
实际运行面数~8 万面
视觉效果以 8 万面的性能开销,实现了 38 万面的细节
额外性能开销

额外优势

  • 美术可以 手动编辑 SVT,对远景进行进一步精修优化
  • 完全无侵入式方案,不改变渲染管线

近景立体贴花(3D Decal)


贴花的重要性

端游 vs 手游的差距

  • 传统手游场景 "干净得不真实",根源是 缺少细节
  • 端游大量使用 贴花(Decal) 来丰富场景:
    • 道路破损、水坑、碎石、裂缝、污渍……
    • 这些小细节让场景 看起来像真实世界
  • 不仅仅是地形问题,贴花影响整个场景的真实感

手游上的贴花困境

  • 传统贴花(Deferred Decal)存在 Draw Call 和 Overdraw 问题
  • 手游上无法大量使用

VT 贴花的优势

  • VT 贴花没有 Overdraw 问题(烘焙进 VT 后,运行时采样成本固定)
  • 三角洲行动使用 大量 VT 贴花:道路、水坑、破损、石块等
  • 效果:极大提升地形丰富度和细节感

立体贴花(3D Decal)——移动端低成本 Tessellation

灵感来源

  • 灵感来自 Fortnite(堡垒之夜) 的分享
  • 目标:在移动端以 低成本 实现类似 Tessellation(曲面细分) 的立体效果

工作原理

制作流程

  1. 对一个普通的 VT 平面贴花(如地面石块纹理)
  2. 制作一个 对应的 Mesh(网格模型)
    • 四周是平的 → 与地形 无缝衔接
    • 中间有凸起 → 模拟贴花对应的立体形状
  3. 该 Mesh 在 Base Pass 中渲染,采样 VT 获取纹理
  4. 简单来说:把地形局部"顶起来"

加载与过渡机制

距离表现
远处(刚加载)Z 轴 Scale = 0 → 完全平坦,看到的是普通 VT 贴花
逐渐靠近Z 轴 Scale 从 0 渐变到 1 → 贴花逐渐"鼓起来"
近处Z 轴 Scale = 1 → 完整的立体石块 / 凸起效果
  • 视觉效果:远处是平面贴花,走近后自然变成立体几何,类似 Tessellation

性能分析

  • 可视范围和加载范围都很小 → 同屏可能只有 几个
  • 使用了 Dynamic Instancing → Draw Call 开销极低
  • 非常划算:少量开销 → 显著拔高品质上限 → 进一步缩小端手差距

性能优化:基于变体与 VT Pass 的 GPU 优化


基于 Shader 变体的优化

问题:远近混合的采样浪费

背景

  • 地形渲染常需要 远近混合(Distance Blending)
    • 近处:使用正常 Tiling 采样
    • 远处:使用 更大 Tiling 采样(避免远处纹理重复感)
    • 过渡区:两者都采样,然后混合

传统方案的问题

方案做法问题
方案 A所有像素都做双倍采样(近 + 远)采样翻倍,浪费严重(大部分像素不在过渡区)
方案 B近处 / 过渡区 / 远处分成不同 Draw CallDraw Call 翻倍

三角洲行动的方案:利用 VT 天然的多 Draw Call

关键发现

VT 本身就需要 多个 Draw Call 来绘制不同 Page 的内容,而 VT 的不同 Page 天然对应不同距离

做法

  • 在 VT Render 的各个 Draw Call 中,根据对应的 距离 选择 不同的 Shader 变体
    • 近处 Page:只采样近处 Tiling → 单次采样
    • 过渡区 Page:打开远近混合 → 双倍采样
    • 远处 Page:只采样远处 Tiling → 单次采样
  • 同样可以用来 区分峭壁区域(峭壁只在特定区域启用 Tri-planar Mapping)
  • 变体控制权交给 VT Render → 统一管理

效果

不损失效果,大幅减少不必要的采样开销


极致优化:按区域材质数选择 Shader 变体

数据分析

  • 以最复杂的 POI 区域 为例,分析每 1 米地形实际使用的材质数量分布
  • 结论:只有 13% 的区域用满了 3 种材质,但 100% 的区域都在运行 3 材质的 Shader

优化方案

  1. 离线计算 每个区域(每 1 米)实际使用的材质数量
  2. VT 渲染时,根据区域选择 不同材质数的 Shader 变体
变体采样次数混合计算
单材质 Shader1 次无需混合
双材质 Shader2 次1 次混合
三材质 Shader3 次2 次混合

关键优势

  • 传统方案做不到:传统 Base Pass 地形无法精细区分每个像素的材质数量
  • VT 方案天然支持 → 灵活性不降低、效果不损失、性能最大化

这是 VT 架构带来的 独特优势:在 VT Pass 阶段可以按区域极致优化 Shader 复杂度,而最终 Base Pass 只需要统一采样 VT 即可。

VT Pass GPU 性能优化


原生 VT Pass 流程分析

原始流程

  • VT Pass 分为两个阶段:
    1. 绘制阶段(Render):将地形材质混合结果绘制到 Page 上
    2. 压缩阶段(Compress):对绘制好的 Page 进行压缩

原生方案的问题

  • 绘制阶段需要支持 半透明(Alpha Blend)Alpha 通道被占用(存放透明度)
  • 实际数据只能放在 RGB 通道
  • 一个最常用的 8 通道 VT(如 BaseColor RGB + Normal XY + Roughness + Metallic + AO)→ 需要 3 张 Render Target(RT)
  • 后果:内存大、带宽高、写入次数多

优化方案:Combine Pass

核心改动

  • 新增一个 Combine Pass 替代原始的半透混合方式
  • 释放 Alpha 通道 用于存储实际数据 → 每张 RT 存 4 个通道(RGBA)

各阶段优化效果

阶段原始方案优化后收益
绘制阶段3 张 RT2 张 RT降低内存、减少写入次数和带宽
压缩阶段读取 3 张 RT → 3 次采样读取 2 张 RT2 次采样降低读取带宽和采样次数

代价

  • 只能支持 Opaque(不透明)Alpha Mask
  • 失去了半透明支持

用 Alpha Mask 模拟半透明

问题

  • 很多 贴花是半透明的(如道路边缘渐变、水渍扩散等),不能直接放弃半透支持

解决方案

与之前峭壁 Tri-planar 过渡区类似的思路

  • 使用 控制 0/1 分布密度的 Alpha Mask模拟 Alpha Blend
  • 原理:
    • 更透明的区域 → 0 的密度更高(更多像素被丢弃)
    • 更不透明的区域 → 1 的密度更高
  • 例如:原始 Alpha Blend 中透明度较高的 texel,在 Alpha Mask 中对应区域 0 的分布更密集

为什么可行

  • 这是在 纹理空间(Texture Space) 上做的 Alpha Mask 混合
  • VT 的 Page 分辨率足够高 → 肉眼完全看不出差别
  • 在 VT 上 几乎可以完全替代半透明

保底方案:优化后的原始半透方案

  • 对于极少数确实需要半透的情况,仍保留优化版原始方案:
    • 利用移动端低成本的 On-Chip Fetch(片上读取,不走外部带宽)
    • 将 3 张 RT 合成 2 张 RT 后再送入压缩阶段
    • 压缩阶段读取带宽仍然 降低 33%

最终整体流程

绝大部分内容 → Combine Pass(2 张 RT,Alpha Mask 模拟半透)
少数特殊需求 → 优化后的原始方案(On-Chip Fetch + 2 RT 压缩)

Overdraw 优化

问题分析

  • 单个 VT Page 覆盖范围只有 0.5 米
  • 贴花经常完全覆盖地形(如道路区域)→ 发生 Overdraw
  • 贴花数量多 → Overdraw 概率高,近处尤为严重(Page 覆盖范围小 + 更新最频繁 = 性能大头)
  • 地形材质比贴花 复杂得多 → 一旦 Overdraw,浪费的性能非常可观

优化策略

策略具体做法
引入 Depth Buffer在 VT Pass 中增加一个 Depth Buffer
调整绘制顺序先画贴花,再画地形
Early-Z 剔除利用 Early-Z 自动剔除被贴花完全覆盖的地形像素 → 跳过复杂的地形着色
CPU 端整体剔除如果一个不透明贴花(如道路中间区域)完全覆盖了某个 Page → 直接在 CPU 端 跳过该 Page 的地形 Draw Call
无贴花区域跳过 Depth如果某个 Page 范围内 没有任何贴花 → 可以 不写入 Depth Buffer,节省开销
  • 整体非常 灵活,根据每个 Page 的实际情况做不同级别的优化

性能对比测试:三角洲行动 vs CODM


测试方法论(严格控制变量)

测试环境

项目设置
测试机型iQOO 17 Pro,骁龙 855
屏幕亮度关闭自动亮度,调至 最低
温度控制每次测试前关闭 APP,等待 CPU 温度恢复至 稳定 39°C,散掉机身热量
帧率锁定除帧率测试外,统一锁定 60 FPS

测试场景控制

  • 三角洲行动选择 材质变化最多的 POI 区域
  • CODM 同样使用 CDLOD 方案的对应区域
  • 为排除 Texture Cache Miss 影响,专门编写了 权重图转换工具
  • 确保 材质分布一致,只有渲染方案本身不同

测试维度

  • 不同 画质档位(高配 / 低配)
  • 静止 vs 运动(运动时 VT 需要更新,压力更大)

测试结果

蓝色 = 三角洲行动,黄色 = CODM

帧率

场景结果
高画质 静止三角洲 更优
低画质 静止三角洲 更优
运动状态三角洲虽因 VT 更新略有下降,但仍比 CODM 高出 50% 帧率

功耗(发热)

  • 三角洲行动在 所有情况下大幅领先
  • 即使运动状态下也优于 CODM
  • 三角洲高配的功耗 < CODM 低配的功耗 ← 极其亮眼的结果

带宽

  • 由于材质方案的天然优势(ID 图 + Texture Array vs 传统权重图)
  • 画质越高、层数越多、采样越多(有无法线等),三角洲的领先幅度越大

GPU 耗时

  • 静止状态下测试 → 大幅度领先
  • 从帧率数据也可间接验证运动状态下同样优秀

核心结论

三角洲行动高配的性能,甚至大幅优于 CODM 低配 同时三角洲还支持 更多材质层数 + 更好的混合品质这就是技术方案选择的力量


实际落地验证

  • 已经历 多轮大规模测试
  • 日常有 每日性能自动化跑车(Performance Profiling) → 及时发现性能回退
  • 示例:小米 11 跑图 11 分钟 的稳定性测试结果良好

总结:端手一体地形方案全景


技术突破全景

维度技术突破
底层方案ID 图 + 权重 + 三角形混合、Adaptive Dynamic Texture Array
材质混合新高度混合算法(统一公式,近处高度混合 / 远处权重混合)
VT 渲染管线CDLOD + VT Render(SVT + RVT 协同)
生态变化Clip Map 技术(颜色、湿度、明暗信息图,133 MB → 2 MB)
峭壁VT 内 Tri-planar Mapping(无额外 Base Pass 开销)
远景SVT 法线烘焙(8 万面实现 38 万面细节,零额外开销)
近景立体贴花(低成本移动端 Tessellation 替代)
性能优化Shader 变体 + VT Pass GPU 优化(Combine Pass、Alpha Mask 模拟半透、Overdraw Early-Z 剔除)

方法论总结

项目最终品质,不是单纯堆技术就行的,落地才是最难的。

  • 每个方案在 设计阶段 就已经与 客户端、TA、美术 充分讨论了落地需要做的事情
  • 技术 + 工具链 + 美术规划 + 性能评估 四位一体
  • 先讨论清楚,再动工 → 避免做完发现落不了地