DOOM(2016)游戏 运行时 画面 猜测

发布时间:2026/7/30 1:18:55
DOOM(2016)游戏 运行时 画面 猜测 原文地址 http://www.adriancourreges.com/blog/2016/09/09/doom-2016-graphics-study/有所改动……随着认知的一些领悟所以修改一些内容 ……现在认可 也是一种技术 方案尽管这个技术方案我本人 目前也是并不十分 赞同由于本人英语水平有限对于图形学技术领悟有限错误之处在所难免读者体谅也欢迎高手 翻译此篇抛砖引玉 。 本文你可以随意转载但请你最好注明出处毕竟我翻译也不容易。请尊重一下劳动成果DOOM2016 画面 研究原文此处有 图片但是我 删除了我感觉 删除掉很多 图片才是很多技术实现原理方式DOOM在1993年开创了游戏设计和开发的根本变革这是一个世界性的现象推动了像 约翰·卡马克John Carmack和 约翰·罗梅洛John Romero这样的标志性 人物。23年后id Software现在属于Zenimax所有的原创始人 暂时 离开……但 并没有什么能阻挡 该机构的 所有 人 来做出一个 超级伟大 的 游戏。新的DOOM2016是专利权的完美补充使用新一代的“ID Tech 6引擎。 ” 整个 游戏源代码 的一部分框架内容 ……前Crytek Tiago Sousa在约翰·卡马克John Carmack离职后现在 担任 首 席渲染程序员 的 角色。在id公司的历史上引擎 我对比其实有疑问 ……源码 开源广为人知新一代游戏引擎通常几年后会 开源引擎 这通常会导致很好的重制和改造。id Tech 6 游戏源代码 的一部分…… 是否开源但仍然有待观察但我们并不一定需要源代码来了解在引擎中实现的 漂亮 图形技术。How a Frame is Rendered(一幁 是如何被渲染的)我们将在下面的场景中 检查 玩家攻击 由一些拥有的敌人防守的gore nest (戈尔巢doom2016游戏的地图之一) 的 场景首先在游戏开始之前先取得Praetor Suitdoom2016 的装甲服装。原文图片删除了容易干扰阅读图片容易干扰阅读很多原理实现方式……与现在发布的大多数Windows 游戏 不同DOOM 2016 并不使用Direct3D 接口但提供了一个OpenGL和 Vulkan后端。Vulkan是新的热点Baldur Karlsson最近在RenderDoc一个 图形调试器支持DX12.dx11,Opengl中增加了支持DOOM2016 是一个很困难的的选择。使用 Vulkan 运行 游戏 在NVIDIA GTX 980上的设置为 最高级别译者注这么翻译 是根据我的 理解Vulkan是一个支持低端机器运行Opengl的渲染接口因此 开到了 最高模式一些猜测来自于 Siggraph大会上Tiago Sousaid首席程序员 和Jean Geffroy.的展示。Megetexture Update (巨型紋理更新)首先第一步是Mega-Texture更新这是一种已经存在于RAGE中使用的ID Tech 5中的技术现在也在DOOM中使用。如果要阐述这个算法的 基本原理 的话这个 算法是在GPU内存上分配了几个巨大的纹理16K x 8k的DOOM每个纹理都是 128 x 128个 Tile( 瓷砖拼图) 拼贴的集合。16k x 8k storage with 128 x 128 pages所有这些Tile(瓷砖)都应该在好的mipmap 级别 代表理想的 实际纹理集合像 素着色器稍后将会 渲染你现在正在看的 游戏画面。当Pixel Shader像素着色器从“虚拟纹理”读取数据时它只能从这些 128x128的某些物理Tile(瓷砖) 中 读取。当然这取决于玩家看的地方玩家移动位置的时候这个画面将会改变新的 模型会出现在屏幕上然后 引用 它 所关联的 虚拟纹理新的Tile图块 将会被 stream in(流式传入)旧的Tile流 将被 导出...所以在一帧的开始DOOM2016 引擎 使用 vkCmdCopyBufferToImage命令来更新 了一些 Tile瓷砖将一些实际的纹理数据 带入 GPU内存。对于 idtech5 megetexture 技术的更详细的一个介绍乃是出自2012年的Siggraphid程序员所写的论文如果感兴趣 05_ip_id_tech5_challenges.pdfH3D姚勇写的 RAGE来了-Megatexture信息更新.pdf 论文对于megetexture的一个叙述对于Megetexture描述更加清晰的论文由id程序员写的Software-Virtual-Textures.pdf如果感兴趣的话其实可以看看……shadow Map atlas (阴影贴图图集对于每个灯投射一个阴影生成一个独特的深度图并将其保存到巨大的8k x 8k texture atlas (纹理图集)的一个Tile(瓷砖)中。然而并不是每个帧都需要计算出每一个深度图DOOM4大量地重新 使用 前一帧的结果并只重新生成需要更新的 深度图。灯 是 静态 的并且仅在 静态对象 上 投射 阴影 时只需 简单地将 其 深度图 保存 8k * 8k的深度缓存器前一幁8k*8k的深度缓冲器 当前一幁 此处 翻译可能有误 ……原样而不是进行 不必要的 重新计算是有 意义的。但是如果一些敌人在光线下移 动则深度图必须再次生成。深度图尺寸可以根据与相机的光距离 来变化重新生成的深度图也不一定保持 在图集内的同一 Tile 内。DOOM2016 具有某些特定的优化例如 缓存深度图 的 静态部分仅计算 动态网格 投影并 合成 结果。Depth Pr-Pass( 深度 预处理)现在渲染所有不透明的网格仅将其 深度信息 输出到 深度图中。首先是玩家的 weapon然后是 静态 几何数据最后是 动态几何 数据。速度图但实际上深度并不是在深度预处理期间输出的唯一信息。虽然动态对象僵尸电缆玩家的weapon被渲染到深度图但是它们每像素的速度也被计算并写入另一个缓冲区以创建 velocity map速度图。这通过在顶点着色器中 计算 前一帧 和 当前 帧 之间 的 每个 顶点 的 位置差 来完成。原文图片 已删除……有需要请看原文 …… Velocity我们 只需要2个channel(通道)来存储 速度红色是沿着水平轴的速度沿着垂直轴是绿色的。这个怪物迅速向玩家绿色移动但是玩家手中的武器几乎没有移动黑色。黄色区域红色和绿色等于1它实际上是缓冲区的 原始默认 颜色没有动态网格没有触及过它是所有的“静态网格区域”。为什么DOOM跳过静态网格的速度计算因为静态像素速度可以从其深度简单地推断出来而相机的状态自上一帧起就是新的state(状态)所以不需要在每个网格的 基础上 进行计算。the velocity速度图 在稍后应用一些 运动模糊 将是有用的。occlusion Quieries( 遮挡查询)我们想发送尽可能少的 几何渲染 到 GPU所以实现这一点的最好方法是剔除玩家视 野里面不能直接 看到的所有网格。DOOM2016 中的大部分遮挡查询都是通过 Umbra中间件 完成的但引擎 仍然会执行一些 GPU遮挡查询 来进一步 削减 视野外的数据……那么GPU遮挡查询背后是怎么实现的呢首先是将游戏场景的几个网格组合成一个包含它们的虚拟框然后请求GPU根据当前的深度缓冲区渲染此框。如果没有一个光栅化像素通过深度测试这意味着 盒子被完全遮挡并且渲染时可以安全地省略该盒子中的 所有 世界对象。那么事情是这些遮挡查询结果是不可用的你不想阻止GPU管道阻挡一个查询。通 常读取结果 被推迟到 以下 帧因此 有必要 使 算法 有点 保守以避免 对象 弹出。Clustered-Forward-Rendering of Opeque Objects(不透明对象的前向渲染)渲染 所有不透明的几何和贴花。照明信息存储在HDR缓冲区中深度测试函数被设置为EQUAL避免任何无用的overdraw过绘制计算由于 之前的深度预处理pre-pass我们知道 每个像素 应具有哪个深度值。当渲染网格时贴图也直接应用 它们存储在 纹理图集 中。它已经看起来很好但我们仍然缺少一些透明的材料如玻璃或颗粒还没有环境反射。关于这个游戏的一趟渲染pass它使用一个聚集的前向渲染器它受到Emil Person和Ola Olsson的作品的启发。历史上前向渲染的一个缺点是它无法处理大量的灯光在 延迟渲染 中 更容易处理。译者注前向渲染在单机fps中 光源数量 可以设定同时一幁内的怪物数量已 知不是mmoprg 玩家人数增多像 中国玩家的有的 “一大群模型在屏幕上呈现”几何数据未知。那么cluster(集群)渲染器是如何运行的呢首先您将您的视口划分成Tile(图块)DOOM创建一个16 x 8细分。一些渲染器会停在这里并计算每个Tile(图块)的灯光列表这有助于 减少照明计算量但 仍然受到一些边缘情况的影响。cluster Rendering(集群渲染)将从2D到3D进一步扩展而不是停止在2D视口 细分它实际上 通过 沿 Z轴 创建 切片 来 执行 整个 相机 平截头体 的3D细分。每个“块”被 称为“群集”您也可以 将其 称为“平截头体” 体素 或 “froxels”。右侧 是 一个 简单 的 4 x 2 视口 细分 的 可视化5个 深度切片 将 平截头体 分为 40个 群集。在DOOM中相机平截头体被分为3072个群集16×8×24个细分深度片 沿着Z轴以对数 方式 定位。使用集群渲染器一个典型的渲染流程 是首先CPU计算影响每个集群内的照明的项目列表灯贴花 和 立方体...为此所有这些项目都“体素化”因此 可以 测试 其 影响 区域 与 集群 的 交集。数据 作为 索引 列表 存储 在 GPU缓冲区 中以便 着色器 可以 访问它。每个群集 最多 可以 容纳256个灯256个贴花 和 256个立方米。然后当GPU呈现像素时从 像素 坐标 和 深度确定 其 属于 的 集群检索 该 特定 集群 的 贴花 / 灯 的 列表。它涉及 偏移 间接 和 索引计算如下 所示。代码 循环 遍历 集群 的 所有 贴花/灯光计算 并 添加 其 贡献。实际上像素着色器可以在此通过期间检索灯光和贴花的列表还有探针列表上图中未显示可以以完全相同的方式访问但在此 通行证 中 未使用所以 我们 稍后 再回来。在CPU上 预先 生成 每个 簇 的 项目 列表 的 开销 是 非常 值得 考虑 的它可以 显着 降低 GPU上的 渲染 计算 复杂度。集群 向前 渲染 最近 越来 越 受到 关注它具有 处理 比 基本转发(此处可能有误.......) 更多 的 亮度 的 好处而比 延迟 更快必须 从 多个 G-Buffers 写入/ 读取。但有一些 我 还没有 提到 的我们 刚刚 检查 的 这个pass通道不仅仅 是一个 写给 照明缓冲区的 前进 的 一个;而 执行 2次 也 使用 MRT 产生 了 2个 G-BuffersNormal MapSpecular Map法线贴图 以 R16G16浮点 格式 存储。镜面图 在R8G8B8A8中 Alpha 通道 包含 平滑 因子。所以 DOOM 实际 上 巧妙 地 混合 了 前进 和 推迟 与 混合 方法。当 执行 附加 效果如反射时这些 额外 的 G-Buffers 将 派上 用场。最后一件事 我 省略了同时也 产生 了一个 160 x 120 的 反馈 缓冲区用于 大型 纹理 系统。它 包含 告诉 流式 传输系统 哪些 纹理 应该流式传输mipmap级别的信息。大型 纹理 引擎 以反应的方式工作在 渲染传递 报告后某些纹理 缺少 引擎 加载 它们。GPU Particles(GPU 粒子)compute shader (计算着色器) 被 分配 到 更新 粒子 仿真位置速度 和 时长 。它 读取 粒子 当前 状态 以及 正常 和 深度缓冲区 用于 碰撞检测起到 模拟步骤 的 作用并将 新 状态 存储到 缓冲区中。Screen Space Ambient Occlusion( 屏幕 空间 环境 遮挡)SSAO Map在此步骤中现在 生成SSAO地图。其目的是使狭窄的接缝褶皱变暗。它也 用于 应用specular occlusion 镜面遮挡以 避免出现在被遮挡的网格上的 明亮照明上 出现 伪影。在从 深度缓冲区正常和 镜面 地图 读取 的 像素着色器 中以原始分辨率的 一半 计算。获得 的 第一个 结果 是 noise( 嘈杂 的)。图像左边Screen Space Reflections( 屏幕 空间 反射)一个 像素着色器 现在 用于 生成 SSR 映射。它仅 使用 存在于屏幕上 的 信息 的 光线 追踪反射使得 光线 在 视口 的 每个 像素 上 反弹读取 由 它们 击中 的 像素 的 颜色。着色器 的 输入 是 深度图用于 计算 像素 世界 空间 位置法线贴图 知道 如何 使 光线反弹specular镜面图知道 反射量和前一帧渲染 在 pre-tonemapping 阶段但 后透明度有一些 颜色 信息。先前 的 帧 摄像机 配置 也 提供 给 像素 着色器因此 可以 跟踪 片段 位置 的 变化。SSR是一个不错的不太 开销大 的技术可以在现场 进行 实时 动态 反射以保持不变 的 成本真正 有助于 沉浸 和 现实 主义 的 感觉。但由于它纯粹在屏幕空间中工作缺少“全局”信息因此它自带的工件。此处翻译可能有误……所以 你 可能 会 在一个 场景 中 看到 很好 的反射但是当你 开始 向下看 时反射的 程度 会 减少直到 看到 你 的 脚 就完全 没有 反思。我发现 DOOM 中 的 SSR 很好地 整合 在 一起它们提高了视觉质量但是 除非 你 真的 专注于 这些否则 你 不会 注意 到 它们 消失。Static Cubemap Reflections静态立体图反射之前所有的动态 反射趟数目及其 限制 现在 都 来自 使用 IBL 的 静态 反射。该技术 基于 预先 生成 的 128 x 128 立方米 表示 地图 不同 位置处 的 环境 照明 信息也 称为 “环境探测”。正如 我们 以前 在 截锥体 聚类 中 所看到的 光 和 贴花 一样探针 也 按照 与 每个 聚类 相同 的 方式 进行 索引。级别的所有立方体都存储在一个数组中其中有几十个但这里是这个场景的5个 主要贡献者这个 房间 内 的 立方体一个像素着色器 从 深度法线 的 镜面 缓冲区 中 读取 立方体 影响 像素 的 群集 结构 立方图 越 靠近 其 影响 越强 并 生成 静态 反射 图Blending Maps Together地图所有 映射 混合在这个步骤中计算着色器组合了之前生成的所有映射。它读取深度和镜面地图并将前进的照明与此处翻译可能有误……SSAO信息当SSR可用于有问题的像素时当SSR信息丢失时静态反射映射数据被用作Fallback(回退)还计算了一些雾效应Particle lighting(粒子照明)我们在这个场景中有一些烟雾粒子照明实际上是根据精灵计算的。每个精灵的渲染就像是在世界空间中从它的位置一些光列表和它们各自的阴影贴图被检索并且quad四边形上的照明被计算出来。然后将结果 存储到 4k地图集的 瓦片中基于距离相机的粒子距离瓦片可以具有不同的分辨率质量设置...图集具有相同分辨率的精灵的专用区域这里是64 x64个精灵而这只是以这种低分辨率存储的照明信息。之后当实际绘制一个粒子时使用全分辨率纹理并将照明四面体放大并与之混合。这是DOOM将粒子照明计算与游戏的实际主渲染分离的位置无论您在播放的分辨率720p1080p4k ...粒子照明总是计算并存储在 这些微小的 固定大小的图块中。Downscale and blur(低档和模糊,downscale我不知道该怎么翻译)场景被缩放了几次下降到40像素。使用分离的垂直和水平通过最小的缩小水平模糊。原图删除了有需要请阅读原文有时候图片是一种干扰……多了 未必就好……为什么这个模糊如此早这样的过程通常在 后期处理过程 中完成以从明亮的地方产生 绽放效应。但是在渲染玻璃折射时所有这些不同的模糊级别将在下一趟中派上用场。透明对象所有透明物体glass(我翻译成视罩因为doom4有头盔嘛)颗粒 都呈现在场景的顶部glass(此处翻译为玻璃)在DOOM中呈现非常好的特别是 磨砂 或肮脏的玻璃贴花仅用于影响玻璃的某些部分使其 折射 或多或少 模糊。像素着色器计算折射“模糊度”因子并从模糊链中选择最接近该模糊因子的2个图。它从这两个地图中读取然后在2个值之间线性插值以逼近折射应具有的最终模糊颜色。这是由于这个过程glass可以在基于像素的基础上以不同的模糊水平产生良好的折射。Distortion Map 失真地图Distortion Map扭曲贴图非常热的地方可以在图像中产生热变形。在这里戈尔巢地图稍微扭曲了形象。对深度缓冲区进行失真以创建低分辨率的失真图。红色和绿色通道表示水平和垂直轴的失真量。蓝色通道包含要应用的 模糊量。实际效果稍后应用于使用失真图的后期处理来知道应该移动哪些像素。虽然在这个场景中 特别是只有一个微妙的失真并不明显。UI 用户界面UI被渲染到以LDR格式存储的预乘法alpha模式中的不同渲染目标。将所有UI都放入单独的缓冲区而不是直接绘制在最终的框架之上这样的优点 是游戏可以一次性在所有UI小部件上应用一些过滤器/后处理如色差或视觉失真。在单程中。渲染不会特别使用任何批处理技术它会逐个绘制UI项目大约有120个绘图调用。在后面的过程中UI缓冲区被混合在游戏图像之上以产生最终结果。Temporal Anti-Aliasing and Motion-Blur时间抗锯齿和运动模糊使用 速度图和先前帧 的渲染结果应用 TAA和 运动 模糊。片段可以被 重新投影因此 像素着色器 知道 当前正在处理的像素位于前一帧中。渲染实际上每隔一帧将网格投影稍微移动一半像素这有助于 删除子像素的别名伪像。结果是非常好的不仅网格边缘变得光滑而且镜像混叠其中一个亮像素将单独弹出一帧也被照顾。通过像FXAA这样的后期处理方法质量远远好于可以实现的质量。Scene Luminance场景亮度该步骤计算场景的平均luminace亮度这是晚些时候提供给tonemapper的参数之一。HDR照明缓冲区在一个循环中被缩减到其分辨率的一半直到它变为2×2纹理每次迭代计算像素颜色值作为其较高分辨率图中其4个父像素的亮度的平均值。应用亮通滤镜来调暗场景最黑暗的区域。然后亮通滤波器的结果在一个循环中被缩小并且在我们之前看到的类似过程 中模糊。层被模糊此处翻译可能有误……高斯模糊分为垂直和水平遍历其中像素着色器计算沿着一个方向的加权平均值。 然后将模糊的层组合起来以创建在原始分辨率的1/4的HDR纹理的绽放。Final Post-Processing(最终后期处理)所有这一步都在一个像素着色器中执行读取失真图数据应用 热失真在HDR照明缓冲区的顶部添加了 绽放纹理 执行如渐晕污垢/镜片闪光 的效果通过对2×2亮度图的中心进行采样并使用附加的曝光参数 来获取 平均亮度应用 调色板 和 颜色分级。Tonemapping之前之后以前下一个12/******************/tonemapping采用HDR照明缓冲器其颜色在广泛的亮度范围内变化并将其转换为每个组件LDR的8位因此可以将框架显示在显示器上。使用基于方程式的A filmic tonemapping operator电影节拍操作员(x(AxBC)DE) / (x(AxB)DF) - (E/F)它是“ 神秘海域2”色谱图也出现在GTA 5(一个电子游戏 )中。请注意场景的所有普通红色都来自于颜色校正。UI and Film Grain (界面和胶片颗粒)最后UI被混合在游戏框架的顶部同时film-grain胶片颗粒被应用。唷我们完成了一幁的流程现在可以将其发送到屏幕的监视器进行显示这是相当多的计算但所有这些都发生在不到16ms。DOOM通过巧妙地重新使用以前的帧中计算出的旧数据从而高性能地产生高质量的视觉效果。总共有1331个draw call(绘制批次)132个纹理和50个渲染目标被使用。Bonus Notes 额外备注Close-Up on Glass玻璃上的特写镜头玻璃渲染是非常好的它是通过我们以前看到的相对简单的步骤实现的准备几层不透明网格渲染的模糊在Foward(前向模式)下使用 贴花/照明/probe(探zhen)反射在前面的方向 绘制 半透明物品使用前面处理过各种 玻璃折射的 模糊值因此每个 像素 可以具有 自身的折射值。景深在在幁数的分析中没有真正显示任何景深所以让我们考虑在应用DoF之前 和 之后 的以下场景并不是所有的游戏都能正确执行DoF传统的方法通常是使用高斯模糊并根据像素的深度在一次通过中进行所有的模糊。这种方法简单而廉价但是有几个问题而高斯模糊对于boken(绽放)来说是不错的创造a bright pixel spread(散景)是不正确的你真的需要一个平坦的内核使一个明亮的像素的光散开在一个圆盘或六边形的形状...高斯不能创造漂亮的散景形状。在单次像素着色器中执行DoF可能会导致 “电子游戏中 显示效果 红色 伪像”。DOOM能正确地执行DoF在我的经验之中doom4使用的方法能够产生最好的结果创建Far_field 远场和near-field (近场)图像根据 其 深度和DoF参数 完成 像素 选择。near-fiedl (近处视野)可以产生增强的模糊效果它会越多流入像素后面越好。远场也模糊但没有从对焦/近场区域读取任何像素因此避免了前景对象错误地 渗透到背景中的任何问题。为了创建boken blur(散景模糊)DOOM以半分辨率工作并使用64个纹理抽头执行disk -blur(磁盘模糊)每个样本都拥有相同的权重因此亮度真正与高斯模糊不同。磁盘直径可以根据像素的CoC值在每像素的基础上变化。然后它进一步扩展了16分针模糊的模糊但这次它不计算加权平均值它只是累积样本值并保持邻居抽头的最高值因此不仅会扩大第一个模糊它也修复了第一次通过的小物体采样间隙。最后一部分是McIntosh的工作灵感。考虑到获得的最终磁盘模糊的宽半径这种在多次通过中的迭代技术可以产生非常好的大模糊同时仍然保持很好的性能每像素执行的实际纹理抽头的数量仍然相当低。远处的图像和近处的图像最终通过Alpha蒙道混合在原始场景的顶部合成以创建最终的景深效果。这个通过在应用运动模糊之前执行。更多阅读如果您想更深入地了解 “idTech 6技术”幸运的是有很多演讲和公共材料可供选择The devil is in the details: idTech 666 Tiago Sousa和Jean Geffroy的对于id tech6游戏引擎的一个更加详细的描述有很多的相关技术。Siggraph 2016 如果感兴趣的话可以下载有的说实话有可以钻研的部分也有未必可以...的越是画面好的游戏越是硬件成本人员素质各种成本有时候太高了实际quake3,doom3很多代码 实现方式 其实就挺好的……Rage后面的很多代码 未必就一定 开发游戏就好掌握各个部分已经多了很多难以避免的复杂度 越来越高很多就未必比以前的老的游戏代码 改动一部分就一定结果好对于游戏开发我现在个人觉得...doom2016的一个论文名字翻译过来为 (“魔鬼”隐藏在 细节 之中)olick的论文叙述了体渲染再加上光线投射即使乃是下一代的趋势如果你对这篇论文感兴趣的话请到下面地址技术采访“数字铸造企业 ”Doomid软件技术采访 DSOGamingQuakeCon 2016Doom Uncapped - Part1和Part 2DoomVentureBeat的最终采访图形学宝典CryEngine 3Sousa_Graphics_Gems_CryENGINE3.pptxSiggraph 2013许多后处理技术都用于idTech 6。写在后面的话译者注我并不完全的赞同作者的全部观点id tech6画面的强大乃是在场景管理多核心的系统优化在加上引擎各个部分的优化,id tech6继承了id tech5的megetexture渲染乃是几何光照纹理最强其他的shader效应未必就是全部我相信随着玩家的硬件的发展id tech6 我看没有使用 体素渲染依然是传统的一些引擎改进了应该是改进了很多的比如 Vulkan支持几何场景管理方式改进了光照纹理很多实际应该好好研究……其他的游戏引擎本身 带动的 几何纹理数据增多画面升级了其他的有待补充