3D游戏渲染:简介


您可以在完美的游戏PC上玩新鲜的《马里奥召唤:死亡任务战场》。看着美丽的超宽4K显示器,欣赏壮丽的风景和复杂的细节。您是否想过图形如何进入屏幕?您是否想过游戏如何使计算机向您展示所有这些内容?

欢迎来到我们的3D游戏渲染之旅:初学者的旅程,从中您将学习如何在屏幕上创建一个基本框架。



每年都会发布数百种针对智能手机,游戏机和PC的新游戏。格式和体裁的种类非常多,但其中一种也许是掌握得最好的-这些是3D游戏。哪个游戏是第一个游戏-值得商question的问题,然后快速浏览一下《吉尼斯世界纪录大全》,就得出了几个结果。它可以被认为是1984年发布的第一款Ultimate Knight Lore游戏,但严格来说,该游戏中的图像是二维的-完全没有使用任何三维信息。

因此,如果我们真的想了解现代3D游戏如何形成图像,那么我们必须从另一个示例开始:Winning RunNamco,于1988年发行。也许这是第一个使用完全不同于现代技术的完全三维游戏。当然,任何年龄超过30岁的游戏都与2018年发布的Codemasters F1完全不同。但是电路图是相似的。


在本文中,我们将介绍使用3D游戏为监视器或电视生成基本图像的过程。让我们从最终结果开始,问自己:“我在看什么?”

然后,我们分析所看到图片形成的每个阶段。在操作过程中,我们将考虑诸如顶点和像素,纹理和通道,缓冲区和阴影,软件和指令之类的概念。我们将找出视频卡如何参与该过程以及为什么需要它。之后,您可以以全新的视角看待您的游戏和PC,并开始更多地欣赏视频图形。

框架选项:像素和颜色


让我们开始3D游戏,作为示例,我们将采用2007年发行的Crytek公司Crysis以下是在其中显示游戏的显示器的照片:


这幅画通常称为相框但是我们到底在看什么呢?我们使用一个微距镜头:


不幸的是,显示器的眩光和外部背光会破坏照片,但是如果我们对其进行一些改进,我们会得到


我们看到监视器中的框架由单独的彩色元素组成的网格组成,如果我们进一步增加它们,我们会注意到每个元素都是三块的块。这种块称为像素(pixel,像素,像素)。在大多数显示器中,像素是使用三种颜色绘制的:红色,绿色和蓝色(RGB,红色-绿色-蓝色)。为了显示一个新的帧,您需要处理成千上万个,甚至不是数百万个RGB值的列表,并将它们保存在显示器可以访问的内存中。这样的内存片段称为缓冲区,即监视器接收帧缓冲区的内容

这是整个过程的最后一点,所以现在我们将朝着相反的方向前进。该过程通常用术语渲染(rendering)来描述,但实际上,这是一系列相互联系的独立步骤,本质上是非常不同的。想象您是一家米其林星级餐厅的厨师:最终的结果是一盘美味的食物,但是要实现这一目标需要做多少工作。与烹饪一样,需要使用基本原料进行渲染。

必要的建筑元素:模型和纹理


任何3D游戏的主要构成要素都是视觉资源,可填充要绘制的世界。电影,电视节目和剧院需要演员,服饰,道具,风景,灯光-清单很长。3D游戏也是如此。您在生成的框架中看到的所有内容都是由艺术家和建模专家开发的。为了更清楚一点,让我们转到旧学校,看看id Software公司的Quake II模型:


游戏问世超过20年前。当时,《雷神之锤II》是一项技术杰作,尽管像那些年的任何游戏一样,这里的模型看起来非常原始。但是,很容易证明它们的组成。


在上一张图片中,我们看到了一个由相互连接的三角形组成的角花鼓。每个角称为一个顶点或一个顶点。每个顶点都充当空间中的一个点,并至少由三个数字表示:坐标x,y,z。但是,这对于3D游戏来说还不够,因此每个顶点都有其他含义:颜色,正面的方向(是的,一个点不能具有正面...只能继续阅读!),亮度,透明度等。


顶点始终具有与纹理贴图相关的一组值。这些是模特穿着的“衣服”的图片。但是,由于图像是平坦的,因此地图应包含从我们可以查看模型的任何方向看的视图。 Quake II的示例说明了一种简单的方法:正面,背面和侧面(手臂)的图像。现代3D游戏已经可以用于具有大量纹理贴图的模型,每个贴图都包含许多细节,并且它们之间没有任何空白。有些地图看起来不像是材质或属性;相反,它们提供有关光如何从表面反射的信息。每个顶点在与该模型关联的纹理贴图中都有一组坐标,因此可以在顶点上“拉伸”。这意味着当您移动顶点时,纹理将随之移动。

在渲染的三维世界中,您看到的所有内容都始于一组顶点和纹理贴图。它们被加载到相互连接的内存缓冲区中。顶点缓冲区(顶点缓冲区)包含纹理和分配给后续渲染的部分内存。命令缓冲区包含指令就如何处理这些资源做一个列表。

所有这些形成了必要的框架,将用于创建最终的彩色像素网格。在某些游戏中,这是大量数据,因为重新创建每个新帧的缓冲区花费的时间太长。游戏还将必要的信息存储在缓冲区中,以形成玩家可以看到的整个世界,或者其中足够大的一部分,并根据需要进行更新。例如,在F1 2018之类的赛车游戏中,所有内容都将存储在一大批缓冲区中。在像Skyrim这样的开放世界游戏中,随着相机在世界范围内移动,数据将被加载到缓冲区中并从缓冲区中删除。

场景设置:顶点


具有所有视觉信息后,游戏将开始视觉显示过程。默认情况下,场景从模型,光源等的基本布置开始于某个位置。这将是“零”屏幕-图形的起点。它通常不显示,仅由系统处理。为了说明在渲染的第一阶段会发生什么,我们将使用在线工具Real-Time Rendering。让我们创建最简单的“游戏”:立于地面的盒子。


该对象包含8个顶点,每个顶点由一个数字列表描述。顶点形成由12个三角形组成的模型。每个三角形,甚至对象本身,都称为图元随着原语的移动,旋转和缩放,数字经过一系列数学运算并被更新。


请注意,模型点号不变。这些数字准确显示了模型在虚拟世界中的位置。相应数学计算的考虑不在本文的讨论范围之内,我们只能说首先将所有对象放置在应有的位置。然后开始着色。


以另一个具有比以前的框多10倍的顶点的模型。在最简单的绘画过程中,获取每个顶点的颜色,然后计算表面之间的颜色变化。这称为插值


增加模型中的顶点数量不仅使您可以创建更多逼真的对象,而且还可以改善颜色插值的结果。


在渲染的这一阶段,可以详细计算场景中光源的效果。例如,模型材料如何反映颜色。这种计算应考虑摄像机的位置和方向以及光源的位置和方向。


为此,有许多不同的数学方法,有些简单,有些非常复杂。在上面的插图中,我们看到右边的对象看起来更好,更逼真,但是绘制它需要更多的工作。

重要的是要注意,现在我们将最现代的游戏中具有少量峰值的对象进行比较。向上滚动并仔细检查《孤岛危机》中的图像:这一场景显示了超过一百万个三角形。以Unigine Valley基准为例,您可以了解现代游戏中使用了多少个三角形。


该图像中的每个对象都由相互连接的顶点组成,这些顶点由包含三角形的图元形成。基准可以在线框模式下运行,其中每个三角形的边缘由白线表示。


如您所见,任何对象都由三角形组成,并为每个三角形计算位置,方向和颜色。这考虑到了光源的位置以及相机的位置和方向。必须将与顶点相关的所有更改都转移到游戏中,以便它具有绘制下一帧的所有必要信息-这是通过更新顶点缓冲区来完成的。

出乎意料的是,这并不是渲染中最困难的部分,有了合适的硬件,所有计算都在千分之几秒内完成!继续。

丢失尺寸:栅格化


在处理完所有顶点并完成所有对象在三维场景中的放置后,渲染过程进入非常重要的阶段。到目前为止,游戏确实是三维的,但最终框架不再是这样:在一系列更改的过程中,观看的世界已从包含数千个连接点的3D空间转换为包含彩色像素的二维图像。在大多数游戏中,此过程至少包括两个阶段:投影屏幕空间(屏幕空间投影)和光栅化


回到我们基于Web的渲染工具,它将向我们展示虚拟世界的体积如何变成平面图像。摄像机显示在左侧,从摄像机发出的线条会形成可见截断的金字塔(视锥),进入摄像机的所有内容都可以显示在最后一帧中。金字塔的垂直段被称为视口-这就是将在监视器上显示。考虑到摄像机的视角,许多数学计算用于将金字塔的整个内容投影到查看区域中。

尽管查看区域中的图形是二维的,但数据仍然是真正的三维,以后,此信息将用于计算哪些图元对我们可见,哪些图元是隐藏的。这可能很难做到,因为即使图元本身对我们是隐藏的,图元也可以投射对我们可见的阴影。从我们中删除隐藏的原语,称为下降(剔除)。此操作会严重影响整个帧的渲染速度。在完成对可见和隐藏图元的分类以及在可见性金字塔范围之外删除三角形之后,完成了三维的最后一个阶段,并使用光栅化将框架制成了完全二维的框架。


上图显示了一个包含一个原始图元的框架的非常简单的示例。像素网格叠加在几何形状上,并标记相应的像素以进行后续处理。最终结果看起来不太像原始三角形,因为我们没有使用足够的像素。在这方面,出现了混叠(混叠,步进线)的问题,可以通过多种方式解决。因此,游戏分辨率的变化(帧中像素的总数)对最终结果的影响很大:更多的像素不仅可以改善表格的显示效果,还可以减少不必要的混叠效果。

完成渲染的这一部分后,我们继续下一步:对帧中所有像素进行最终着色。

承载光:像素级


我们已经进入了渲染的最困难阶段。一旦涉及到使用像素信息(最初从顶点获得)来穿衣服(纹理)模型。然而,事实是,尽管纹理和框架本身是二维的,但是,顶点处理阶段的虚拟世界却发生了扭曲,移动和改变。为了解决所有这些问题,使用了额外的数学计算,但是,新的问题可能是结果的特征。


在此插图中,棋盘格纹理应用于平面。存在令人不愉快的视觉波动,这种现象会因混叠而加剧。要解决此问题,请使用较小版本的纹理贴图(多个贴图,mipmap),重复使用这些纹理中的信息(过滤,过滤)以及其他数学计算。效果明显:


对于任何游戏而言,这确实是一个困难的步骤,但如今已不再如此,因为由于广泛使用其他视觉效果(例如反射和阴影),纹理处理已成为渲染过程中相对较小的阶段。当以高分辨率播放时,光栅化和像素处理阶段的负载会增加,但这对顶点处理的影响相对较小。尽管由于光源引起的主要着色是在顶点阶段进行的,但可以应用更复杂的照明效果。


在上一个插图中,我们不再看到不同三角形之间的颜色变化,这给了我们光滑无缝物体的感觉。尽管在此示例中,球体与上图中的绿色球体由相同数量的三角形组成,但由于像素着色过程,在我们看来,使用了更多的三角形。


在许多游戏中,像素阶段必须运行几次。例如,为了使镜子或水面反射周围的世界,必须首先绘制此世界。每次运行称为通过(pass),要获得每帧的最终图像,可以轻松地进行四次或更多次使用。

同样,有时您需要再次运行顶点舞台,以从另一点重新绘制世界,并在显示给玩家的场景中使用此图像。为此,请使用单缓冲区渲染(渲染目标)-使用缓冲区作为帧的最终存储,但也可以通过不同的传递充当纹理。

要评估像素级的复杂性,您可以阅读Doom 2016中的框架分析创建一帧所需的操作数量会让您感到震惊。


无论是最终结果还是中间结果,创建帧所完成的所有工作都必须保存到缓冲区中。通常,游戏在飞行中至少使用两个缓冲区进行最终显示:一个缓冲区用于“当前工作”,第二个缓冲区正在等待监视器的访问,或者处于显示过程中。您始终需要一个屏幕缓冲区,用于保存渲染结果,并且当所有缓冲区都已满时,您需要继续并创建一个新缓冲区。完成该帧的工作后,将给出一个简单的命令,交换最后的帧缓冲区,监视器将接收到最后渲染的帧,然后开始渲染下一帧。


刺客信条奥德赛的这一帧中,我们看到了完整帧缓冲区的内容。此内容可以在仅包含数字的表中表示。它们以电信号的形式发送到监视器或电视,并且屏幕上的像素会更改其值。我们的眼睛看到的是平坦的实心图像,但是我们的大脑将其解释为三维。游戏中只有一张镜头的场景隐藏了太多的工作,因此值得一看的是程序员如何处理它。

流程管理:API和说明


弄清楚如何使游戏执行和管理所有计算,顶点,纹理,照明,缓冲区等。 -这是一项艰巨的任务。幸运的是,请在此编程接口(应用程序编程接口,API)中帮助我们

渲染API通过提供结构,规则和软件库来降低总体复杂性,这些结构,规则和软件库允许使用与硬件无关的简化指令。以过去三年中为PC发布的任何3D游戏为例:它是使用三种流行的API(Direct3D,OpenGL或Vulkan)之一创建的。还有其他类似的发展,尤其是在移动领域,但是在本文中,我们将讨论提到的三个。


尽管指令和操作的名称有所不同(例如,用于DirectX中处理像素的代码块称为像素着色器,而在Vulkan中称为片段着色器),但最终结果没有不同,更确切地说,它应该没有差异。

区别将体现在用于渲染的设备上。 API生成的指令需要转换为设备驱动程序处理的硬件友好命令。设备制造商必须花费大量资源和时间来使驱动程序尽快,正确地执行此转换。


例如,《The Talos Principle》(2014年)的早期Beta版支持上述所有三个API。为了演示驱动程序和接口的不同组合的结果如何不同,我们通过将分辨率设置为1080p和最大质量设置来运行标准的内置基准测试。英特尔酷睿i7-9700K处理器可以正常工作,而无需超频,英伟达Titan X(Pascal)视频卡,RAM-32 GB DDR4 RAM。

  • DirectX 9 =平均188.4帧/秒。
  • DirectX 11 =平均202.3帧/秒。
  • OpenGL =平均87.9帧/秒。
  • Vulkan =平均189.4帧/秒。

我们不会分析结果,他们当然不会说某些API比其他API“更好”(请记住,该游戏的beta版已经过测试)。我们只会说,为不同的API编程会带来各种困难,并且在任何给定的时间性能也会有所不同。通常,游戏开发人员会选择具有更多经验的API,并为此优化代码。有时,引擎一词用来描述负责渲染的代码,但严格来说,引擎是一整套工具,可处理游戏的各个方面,而不仅仅是图形。

从头开始创建渲染3D游戏的程序并非易事。因此,今天在许多游戏中都使用了许可的第三方系统(例如,虚幻引擎要评估它们的复杂性,请为Quake打开开源引擎并查看gl_draw.c文件:该文件包含有关不同渲染操作的指令,并且仅反映了整个引擎的一小部分。但是Quake发行于20年前,整个游戏(包括所有视觉资源,声音,音乐等)需要55 MB。为了进行比较,在《孤岛惊魂5》中, 着色器占用62 MB。

时间最重要:使用正确的设备


以上所有内容均可由任何计算机系统的处理器计算和处理。 x86-64系列的现代处理器支持所有必要的数学运算,甚至为此包含单独的子系统。但是,渲染单个帧的任务需要大量重复的计算和大量的工作并行化。中央处理器不适合这样做,因为它们是为解决尽可能广泛的任务而创建的。用于图形计算的专用处理器称为GPU(图形处理单元)。创建它们是为了DirectX,OpenGL和Vulkan。

我们将使用基准测试,使您可以使用中央处理器或专用设备渲染帧-V-ray NEXT混沌集团公司。实际上,它进行光线追踪而不是渲染,但是这里的大多数数值运算也取决于硬件。


让我们以三种模式通过基准测试:仅中央处理器,仅图形处理器,以及两种处理器的组合:

  • 单单CPU = 5300万条光线
  • 仅GPU就有2.51亿条光线
  • 两种处理器的组合= 2.99亿条射线

度量单位可以忽略,本质是相差五倍。但是,该测试与游戏的关系并不大,因此让我们转向老式基准测试Futuremark 3DMark03让我们运行一个简单的Wings of Fury测试,使用中央处理器强制计算所有顶点着色器(即,具有用于移动和着色三角形的整套操作)。


结果不应该让您感到惊讶:

  • 中央处理器=平均77帧/秒。
  • GPU =平均1,580帧/秒。

当所有的顶点计算都由中央处理器执行时,渲染和显示每个帧平均需要13毫秒。使用图形处理器时,该数字下降到0.6毫秒-快20倍以上。

如果您运行最困难的基准测试-大自然,差异会更大。中央处理器产生了微不足道的3.1帧/秒!图形处理器的速度达到1388帧/秒:快了450倍。请注意:3DMark03 16出来了,并且在中央处理器上的测试中,仅处理了顶点,图形处理器仍然承担光栅化和像素阶段。试想一下,如果基准是现代的,并且大多数操作是以编程方式执行的?


现在,我们将再次尝试Unigine Valley基准测试,其处理的图形与《孤岛惊魂5》等游戏中使用的图形非常相似。除标准DirectX 11外,还有一个完整的软件渲染引擎。在视频处理器上运行时,平均结果为196帧/秒。那软件版本呢?在几次崩溃之后,一台功能强大的测试计算机平均产生了0.1帧/秒的速度。 - 慢了将近2000倍

产生如此大差异的原因在于3D渲染中使用的数学计算和数据格式。 CPU的每个内核都配备了浮点模块。 i7-9700K包含8个核心,每个核心具有两个这样的模块。尽管Titan X中模块的体系结构不同,但是两种类型都可以使用相同格式的数据执行相同的计算。该视频卡具有3500多个模块,可以执行可比的计算,尽管它们的时钟频率比中央处理器(1.5 GHz和4.7 GHz)低得多,但是视频处理器占用的模块数却很多。

尽管Titan X不是大众图形卡,但即使是预算模型也将取代任何中央处理器。因此,所有3D游戏和API都是为专用设备而设计的。您可以下载V-ray3DMark任何Unigine 基准 并测试您的系统-亲自了解视频处理器在游戏中渲染图形的适应程度。

最后的话


从空间上的点到显示器上的彩色图像,这与在3D游戏中创建单个帧的过程只是一小段距离。

实际上,整个过程只是处理数字。但是,很多内容仍不在本文讨论范围之内。我们没有考虑由欧氏线性代数,三角函数和顶点和像素着色器执行的微分计算的具体数学计算。我们也没有讨论使用统计采样如何处理纹理。我省略了一些很酷的视觉效果,例如使用扩展的动态范围和时间平滑功能,在屏幕空间中阻挡环境光,减少对光线跟踪的干扰。

下次您发布现代3D游戏时,我们希望您不仅能以不同的眼光看图形,而且希望对它有更多的了解。

All Articles