导语:在今年的游戏开发者大会(GDC 2024)上,来自腾讯游戏的专家持续带来前沿分享,围绕AI、渲染、跨端游戏开发、动画等游戏技术应用及游戏制作,引发同业关注。本文为“暗区突围手游:在移动端打造次世代射击游戏”分享的图文版干货内容。
分享嘉宾:王俊宏 腾讯互娱魔方暗区突围手游项目图形程序负责人
大家好,感谢大家参加本次会议。我叫王俊宏,是魔方工作室暗区突围渲染组的主程。我在腾讯工作了12年,一直从事PC和移动游戏开发。
我将从介绍《暗区突围》手游和移动光线追踪的背景开始,然后介绍《暗区突围》中的光线追踪,包括光线追踪场景管理、反射、软阴影、环境遮挡和优化,最后是一些结论。
一、背景介绍
《暗区突围》是一款面向Android和iOS设备的下一代沉浸式第一人称战术射击手游。该游戏于2022年7月正式发布。制作人孙一鸣去年在GDC上介绍了游戏玩法。游戏使用的是Unreal Engine 4.26引擎。也是一款开放世界游戏。例如,最新的关卡矿区, 大小约为4公里乘以4公里。场景中有超过10万个网格实例和3000多个流式加载关卡。因此,场景管理将是一个挑战。
我们游戏中的一些重要渲染特性包括:首先,渲染管线采用的是前向渲染管线。其次,我们使用了基于物理的渲染,包括基于物理的材质、光照、相机和着色。例如,这个视频展示了游戏中的自动曝光功能。
第三个重要特性是动态天气系统,我的同事陈家铭在2022年的GDC上介绍过。在这个视频中,阳光、天空光和云都会随着时间变化。
最后,我们游戏中的全局光照基于预计算辐照度传输。因此,在这个视频中,当天气系统变化时,间接光也会有所不同。
接下来,我将介绍移动光线追踪的情况。现在最新的智能手机已经支持硬件加速的Ray Query(也称为Inline Ray Tracing)。Ray Query可以在任何着色器阶段使用,例如顶点着色器、像素着色器或计算着色器。然而,在移动设备上调试光线追踪仍然具有挑战性,因为大多数截帧工具和GPU性能分析工具都不支持移动端的Vulkan Ray Query。
在我们集成光线追踪之前,有一些准备工作需要完成。首先,我们启用了Android的Vulkan API。然后,更新了Shader交叉编译工具到最新的Shader Conductor,以支持光线查询的着色器指令。最后,我们扩展了UE4的Vulkan和Metal RHI。
二、《暗区突围》手游中的光线追踪
现在,我来介绍《暗区突围》手游中的光线追踪。在中国,带有光线追踪功能的Android版本已于2023年发布。而iOS版本的光线追踪功能正在开发中。正如视频所示,我们已经集成了光线追踪的反射、软阴影和环境光遮蔽。接下来我将展示在智能手机上拍摄的截图。
这是在智能手机上的截图,如果禁用光线查询,大理石地板上不会有反射效果。
但是,如果启用了光线查询,我们将获得令人印象深刻的光泽反射效果。
这是另一张在室外拍摄的截图,轮胎、箱子和地板上没有环境遮挡效果。
当启用光线追踪的环境遮挡时,间接光效果更加逼真。
当禁用光线查询的软阴影时,我们使用CSM阴影和硬件PCF。但是阴影贴图的分辨率不足以为金属栅栏或其他一些细小物体渲染清晰的阴影。
启用光线追踪软阴影后,我们可以获得几乎完美的软阴影效果。所有这些可以为玩家创造更加真实和具有沉浸感的体验。
正如我之前提到的,对于我们来说,管理光线追踪场景是一个挑战。稍后我将介绍我们所面临的挑战以及应用的优化方法。
以下是三个主要挑战:第一个挑战是底层加速结构(BLAS)的内存占用。第二个挑战是在移动GPU上构建BLAS的计算成本较高。第三个挑战是在具有太多实例的顶层加速结构(TLAS)中Trace非常耗时。这是在PC上使用NVIDIA Nsight Graphics捕获的截图,显示了我们游戏中部分TLAS实例的情况。
首先,我将介绍目前场景管理的基本情况。我们的关卡是由关卡流式加载系统管理的。当加载包时,会加模型的底级LOD。更高级的模型LOD则由模型流式加载系统加载。而一些带有遮罩、世界坐标偏移或透明材质的模型不会创建BLAS。那么,我们能否在加载模型LOD时创建BLAS呢?答案是否定的。因为当加载地图时,会创建超过4700个BLAS,显存占用高达4.4GB,然后游戏会因为内存不足而崩溃。
我们使用了一个简单的算法来管理BLAS。在这个图中,P是相机的位置,r1是BLAS创建半径,r2是BLAS销毁半径,d是相机到物体边界球的距离。如果d小于r1,将标记为待创建;如果d大于r1且小于r2,将标记为待保留。然后,我会立即处理待创建请求。但对于没有待创建或保留标记的BLAS,将会被延迟销毁。这样可以避免物体靠近边缘时频繁创建和销毁。
这里所有参数都是可调的。经过优化,BLAS的数量从4700个减少到约700个。视频内存从4.4GB减少到了1.1GB。
对于TLAS,我们每帧更新一次,并在构建时启用Fast Trace标记。我们还使用距离剔除和投影角度剔除来优化实例数量。应用这些优化后,图中TLAS实例数量降为600个左右。
这是在名为Vivo X90的智能手机上的性能数据。构建BLAS的成本小于0.5毫秒。构建TLAS的成本约为1毫秒。
接下来,我将介绍光线追踪的反射,重点介绍渲染管线部分。
使用Ray Query实现反射面临几个挑战。第一个挑战是如何对反射像素进行着色。在Vulkan Ray Query中,没有RTPSO。而且我们的游戏中没有Bindless Texture。但是场景中有成千上万种不同的材质。不可能使用一个通用着色器来对其进行着色;第二个挑战是当前的渲染流程是正向渲染,我们需要为反射创建一个混合渲染管线;第三个挑战是性能。例如,耗电和帧率。
这是《暗区突围》手游的Ray Query反射渲染管线。第一个渲染Pass是Base Pass,它会获取所需的像素信息。第二个Pass是Query Scene Pass,我们发射光线以获取屏幕空间中每个像素的网格和三角形信息。第三个Pass是可见性解析Pass,该Pass将为每个像素计算反射颜色。接下来的两次渲染使用联合双边滤波来获取光泽反射纹理。最后,将光泽反射纹理与场景颜色混合。稍后我将介绍关键步骤。
以下是一些准备工作。在资源烘焙过程中会生成用于渲染反射颜色的着色器。在运行时,我们将收集用于对反射着色的绘制命令,并在每帧重新分配网格实例ID和命中组ID。
然后,我将介绍渲染流程中的关键渲染步骤。在Base Pass中,我们将渲染一个额外的Render Target。它存储了法线、粗糙度和一个标志位。我们称之为Thin G Buffer。中间的图像是Thin G Buffer。
下一个是Query Scene Pass。由于光线查询中没有光线追踪管线状态对象(RTPSO),所以我们使用Query Scene Pass和Visibility Resolve Pass代替。在Query Scene Pass中,我们重构世界位置和反射光线方向。然后发射一条光线,如果击中任何实例,则存储实例ID、三角形ID和击中点的重心坐标。左侧的图像存储了打包的三角形ID和重心坐标。右侧的图像存储了模型绘制ID。
对于Visibility Resolve Pass,我们提交可见性解析的Draw Call命令,并且使用Uniform Buffer提交绘制ID。每个Draw Call都是一个全屏四边形。对于GPU而言,如果绘制ID不匹配,像素将被丢弃。我们使用Manual Vertex Fetch和重心插值来计算像素着色器中的PBR参数。然后发射一条阴影光线以获取阴影值。最后计算反射颜色并写入反射Render Target。
这种算法的优点是硬件兼容性好,易于集成。但缺点是Draw Call以及Overdraw太高。因此,我们使用GPU遮挡查询来删除不可见的网格绘制命令,并使用深度测试来消除过度绘制。这张图展示的是深度缓冲区,它存储了网格绘制ID。
优化之后,可见性解析绘制调用从600多个减少到约110个。并且完全消除了Overdraw。这张图片展示了可见性解析的结果。
之后的模糊处理Pass使用了联合双边滤波器。输入是Thin G Buffer、反射纹理和深度纹理。我们使用一个核偏移来根据粗糙度调整核大小。右侧的纹理是光泽反射纹理。
第二次模糊处理与第一次几乎相同,但使用了更大的卷积核偏移。
这是混合的结果。可以看到边缘被保留了下来。对于光滑的地板,反射很清晰,而对于粗糙的墙壁,反射较模糊。对于完全粗糙的材质,在这里不会发射任何光线。
因此,最终我们获得了良好的硬件兼容性和高性能。对于Dimensity 9200,我们的帧率超过了60帧。这里也有一些缺点。例如,处理透明或遮罩材质比较困难。
下面我将介绍光线追踪的软阴影和环境光遮蔽。
软阴影和环境光遮蔽都需要发射大量的射线。这是使用1条阴影射线和1条环境光遮蔽射线的结果,图像充满了噪声。
这是软阴影和环境光遮蔽的渲染管线。我们使用完整的Pre Pass来获取几何法线和深度。然后Query Scene Pass发射光线,它将输出带噪声的阴影和环境光遮蔽结果。接下来的渲染步骤是空间-时域降噪。最后,Base Pass将采样去噪后的阴影和环境光遮蔽结果。
对于Query Scene Pass,阴影和环境光遮挡效果会各发射一条射线。三角形背面不发射阴影射线。对于这个Render Target,R通道是阴影,G通道是环境光遮蔽。两者都充满噪点。为了提高性能,还可以使用较低的渲染分辨率。
左侧是没有降噪的图像,右侧是经过时域降噪后的图像。这里大部分噪声都被去除了。
这里还应用了A-Trous滤波器进行去噪。经过两次处理后,我们得到了右边的结果。
左侧图像展示的是阴影,可以看到边缘非常柔和。右侧环境光遮蔽的质量也非常高。
下面是游戏里最终的结果。
对于Dimensity 9200系列芯片,我们实现了超过70的渲染帧率。
这里也有一些缺点。例如,具有遮罩的材质需要使用其他阴影算法。对于透明表面,阴影和环境光遮蔽会得到错误的结果。实际上,这里的玻璃阴影是不正确的。而且过多的渲染Pass和纹理采样会导致较高的功耗。
我们还应用了其他一些优化。例如帧预测,我的同事齐越也在GDC会议介绍了它(在移动端实现144帧渲染:《暗区突围》手游中的帧预测)。
结果
最后,我将会展示一些结果。这是Ray Query的详细性能数据。它可以平稳地运行在60帧每秒。
平均功耗约为3000 mw。
最后一部分是致谢。我们的项目成员包括钟建斌、高锴庚、齐越和崔世文。上述所有工作都离不开整个团队的共同努力。还要感谢我们的合作伙伴MediaTek和Vivo。
这里还有一些参考资料。最后感谢大家今天的到来!
来源:腾讯游戏学堂