模型如何以及何时向世界,世界观察,等等乘法发生?

我学习了游戏devise的matrix变换,并且与一些基本概念纠缠在一起。 我看到在按照这个顺序渲染之前发生的实际乘法:

  1. MODEL into WORLD :将每个模型的顶点乘以worldMatrix。 如果模型很大,那对GPU来说有点压力。
  2. 世界进入VIEW :好吧,如果Model to World糟糕,那么用一些matrix乘以整个世界模型是GPU的巨大负担。 那么为什么在每本书的作者都说这样做更好呢? VIEW只是一个点(一个顶点),更改一个顶点要比数百万更容易。
  3. 那么这个序列中的任何其他步骤都与我无关。 因为我不相信任何人会进行这样的乘法运算。

我敢肯定,没有人乘以任何matrix的世界顶点,如果我在这里,那么整个乘法堆栈的变换发生? 我想我错过了一些低级的理解。

PS所以强调一下我的观点:为什么要用全部的东西来繁衍整个世界呢? 我只会看到它的一部分! 在游戏引擎(openGL,ect)中如何避免这种巨大的乘法。

PSS感谢您的答案家伙! 巨大的工作只是为了帮助我____这些都是我在任何stachexchange论坛上得到的最详细的答案。 🙂

PSSS我来自财务数据的二维可视化。 你们中的一些人指出,这可能是我误解为什么每个世界物体必须被处理的原因。 我的管道:

  1. 对象\模型空间=只是一堆酒吧和价格的数据系列。 这是一个2D对象,在X方向上具有“条”单位,在Y方向上具有“价格”单位。 所以通过使用“我” Serie.bar[i]在这个数组中导航。 我通常说数据序列在“数组空间”,因为我使用“我”来导航那里。
  2. 世界空间= 2个数据序列可以共存的地方。 例如,您可以将谷歌和特斯拉的价格放在相互叠加的相同图表上,以进行相关性分析。
  3. 相机空间 – 世界坐标中的一个二维矩形。 例如, camera.width=300bars, camera.X =11000bar, camera.Y=33 $ per share.

使用鼠标,用户只更换相机(这就是为什么当有人说视图不应该移动,世界应该移动时,它是超级有线的。 相机坐标变化,当它是时间渲染,你只需看看相机内部,做这样的事情: for (int i = camera.left; i < camera.right; i++) { g.DrawSerie(google.bar[i]); } 所以你看,这里没有必要和世界的转变。 我知道所有我需要渲染之前感谢“相机在世界坐标”。 我想你不能在3D中做,但一些细节仍然缺less我。

从逻辑上考虑:

当你渲染什么东西时你的目标是什么?
要在屏幕上显示它!

什么是约束?
模型必须对相机可见(即在视锥体中,不被其他物体遮挡等)

什么是投入?

  1. 模型原点本地坐标系中的顶点集合。
  2. 一个转换matrix,描述模型在游戏世界中的位置和方式。

什么是输出?

  1. 视图空间中的顶点集合(即相对于视图,通常由单个“照相机”定义),可用于生成片段,然后成为标准化设备坐标中的像素(就像2D游戏一样,屏幕是2D毕竟)。

这个过程是这样的:

  1. 首先,从模型空间中的顶点列表(相对于模型原点/坐标系)开始。 这使您可以轻松修改游戏外的网格(例如在Blender中),因为坐标系统是独立的。
  2. 然后,顶点被转换到世界空间(相对于游戏世界原点/坐标系或游戏块原点)。 这可以让你做碰撞检测或其他游戏世界相关的逻辑。
  3. 接下来,将顶点转换为查看空间(相对于相机原点/坐标系),以便您可以决定相机可见的内容。 一种这样的技术被称为“平截头体剔除(frustum culling)”,并且要求渲染器忽略相机后面或者视野外的顶点。
  4. 最后,将视图空间顶点转换为标准化的设备坐标,以便可以对片段进行深度testing,混合以及可以应用任何其他后处理效果(例如着色器)。 这是必要的,因为它允许您计算最终的颜色以显示在屏幕上的每个像素上。

我想如果你没有游戏世界,你可以消除世界空间计算步骤,直接从模型空间去查看空间(本质上,你会说你的模型空间你的世界空间),但这意味着你只能有全世界只有一个物体,而且没有办法做任何游戏世界的具体逻辑,比如多个物体之间的碰撞。 一般来说,这不是很有用。

正如你所看到的,所有这些步骤不仅是必要的,而且后面的步骤实际上是巨大的优化(例如截锥体剔除),因为它们可以帮助你避免渲染场景中的大部分东西(尤其是小的封闭诸如建筑物内部的区域)。 当你站在一个没有窗户的3000顶点小屋内时,为什么要花费时间渲染400,000,000个顶点森林?

MODEL into WORLD:将每个模型的顶点乘以worldMatrix。 如果模型很大,那对GPU来说有点压力。

这实际上不是一个“压力”。 GPU是量身定制的硬件,可轻松执行数十万次操作。 这很重要,因为它似乎是你混乱的根源。 这只不过是你想象的那么大。

世界进入VIEW:好吧,如果Model to World不好,那么将整个世界充满模型乘以一些matrix是GPU的巨大负担。

事实上,除非某些顶点着色器需要在世界空间中做某些工作(这并不总是必要的,这一步和前一步是结合在一起的),也就是模型到世界和世界到视图matrix相乘在渲染之前一起渲染一次,每个渲染的顶点只有一次被合并后的matrix相乘,光照工作有时是在视图空间中完成的,所以变换往往会暂停,但是也可以将整个世界 – >视图 – 如果在视图空间中不需要做任何事情,则将空间转换成单个matrix。

这进一步降低了转换的有效成本。

VIEW只是一个点(一个顶点),更改一个顶点要比数百万更容易。

不,这个观点在概念上是一个点和一个基础(一个旋转的参照系)。 你不能“只是改变看法”。 你最终需要知道所有顶点相对于视图的位置和方向的位置,所以你必须变换所有的顶点。 您可以在世界空间中使用您的视图的位置和方向来完成一些照明工作,但最终您仍然需要相对于视图框架的坐标来裁剪它们以抵制视锥,所以这是一个有争议的问题。

我敢肯定,没有人乘以任何matrix的世界顶点,如果我在这里,那么整个乘法堆栈的变换发生? 我想我错过了一些低级的理解。

你不对。 世界顶点乘以matrix将它们带入剪辑空间。

几何变换管道非常简单:几何graphics从模型空间开始,转换到世界空间,然后查看空间,然后剪切空间,剪切平截面。 然后应用透视分割,坐标转换为标准化的设备坐标,最终转换为光栅化的窗口坐标。

没有隐藏的技巧,事实上,有时候可以跳过你不需要通过组合matrix显式地进入的空间(例如,将模型空间顶点乘以组合的世界视图投影matrix来右移到剪辑空间)。 在逐个顶点的基础上进行这种转换的代价是非常小的。

请允许我详细说明在最常见的情况下,GPU的责任应该是什么,以及CPU,游戏引擎和OpenGL的责任。


OpenGLstream水线的基础知识

首先,在OpenGL渲染stream水线的情况下,GPU有一个顶点着色器程序,一次只能处理一个顶点。 这个顶点被3个特殊的matrix转换(按此顺序):

  1. 模型matrix – 顶点取自局部模型坐标并放置在世界坐标中。 这是您将模型定位/定向/缩放到相对于整个场景的适当位置的地方。
  2. 视图matrix – 顶点被转换成看起来像是从特定的位置,角度和距离观看的。 这模仿了相机可能的行为; 然而,在OpenGL中,只有1个摄像头(它总是面向屏幕)
  3. 投影matrix(Projection Matrix) – 顶点根据视锥的参数进行变换。 这是发生视角分割的事情(在透视投影的情况下)。

经过顶点着色器处理后,变换后的顶点在原始assembly过程中与其他顶点合并,然后再进行光栅化和分片处理等操作。


谁负责什么?

您的初步观察是有效的,如果GPU处理大场景的每个顶点,则可能会强调GPU。 这意味着我们必须小心处理发送给GPU的内容。 正如您所指出的,浪费GPU时间来处理屏幕上永远不会结束的事情是毫无意义的。 所以,在游戏devise中,游戏引擎必须以某种方式决定如何管理场景的哪一部分。 有很多方法可以做到这一点,但我会列举几个:

  • 游戏引擎可以将地图分成几个部分,只能在观察者/玩家一定距离内渲染对象。 可选地,使用雾使没有内容的世界部分逐渐接缝。
  • 游戏引擎可以控制细节水平,因此可以在差异可忽略的情况下使用低多边形模型(例如距离模型)。
  • 游戏引擎可以查看场景的哪些部分可能被前面的那些遮挡。 游戏引擎并不依赖于深度testing,而是可以首先忽略所有这些顶点被发送到GPU! 这对渲染城市特别有用。
  • 而不是依靠预建引擎的机制,你可以编写自己的控制如何使用GPU。

所有上述游戏引擎优化都发生在CPU上,因为它们涉及决定发送给GPU的数据。 但是,GPU和OpenGL管道还提供了其他优化。 这包括诸如按样本操作和testing (如深度testing)之类的内容,还包括视图裁剪等内容。 在裁剪的情况下,这防止了视锥之外的顶点被进一步处理。

OpenGL还提供了一些更多的优化方法,允许您通过使用顶点数组对象和各种types的缓冲对象将模型卸载到GPU内存中。 OpenGL也有不同的渲染模式,比如索引渲染 ,可以减less实际发送给顶点着色器的顶点数量。

至于优化,主要有两个地方,你最省时间。

  1. 首先,通过决定发送给GPU的内容(这些是游戏引擎优化),可以节省大量的时间。
  2. 其次,您可以通过将数据卸载到GPU来节省大量时间,而不是每次渲染帧时从CPU发送数据。 一旦进入GPU内存,绘制模型变得非常快。

许多其他的优化仍然是有用的,但只能削减less量的处理时间。


我希望这有助于为您提供所需的“低级”理解。 随意提问如果有什么不清楚的地方!

我认为其他答案已经涵盖了这个大部分,但我想在PS上做一些断言:

PS所以强调一下我的观点:为什么要用全部的东西来繁衍整个世界呢?

因为世界空间不匹配,所以是在屏幕上的表示。 例如,在2D游戏中,您可能会轻视将偏移量应用于世界的位置,并只画出屏幕上的内容…而不是3D。 为什么? 因为你有旋转和透视。 为了存档这些效果,我们使用matrix转换。

那没有解决堵塞的问题。 如果不改变摄像头坐标,就无法告诉对象隐藏了另一个对象,因此我们需要进行转换。

此外,考虑到您可能需要额外的几何形状(在视锥之外)来制作其他效果,如阴影或reflection。

我只会看到它的一部分! 在游戏引擎(openGL,ect)中如何避免这种巨大的乘法。

游戏引擎可能需要额外的工作来保持GPU和CPU的低负载。 需要指出的是,video游戏长期以来一直在使用我所描述的技术,现代GPU硬件比第一次引入时要好得多。

将这些技术结合起来,可以让巨大的开放游戏拥有数千或数百万个对象,将所有内容发送给GPU确实会对性能产生影响。

例如,游戏引擎不再仅仅依靠3D的画家algorithm; 相反,引擎将遮挡问题留给了GPU,由于深度缓冲区,GPU可以处理交错的三角形。 虽然有引擎可以优化遮挡的情况,但并非一般情况。


二进制空间分区

让我们从古老的厄运开始。 原来的厄运是当时硬件的制约因素。 该发动机是基于Wolfenstein 3D的发动机,该发动机是通过射线投射来发现水平视野与墙壁之间的距离,并在屏幕上缩放它们以产生透视效果。

Doom在地图上添加了垂直层次,这意味着当发现地板上的一个台阶时,发动机必须重新检查该区域以find在recursion过程中超出该步骤的区域…这意味着“复杂”的垂直结构(楼梯)非常重视性能。

该解决scheme是一种称为BPS(二进制空间分区)的技术, 通常意味着将世界分成两半(做一个二进制分区),然后再一次,所以…将整个结构添加到树结构可以通过导航find附近的物体或物体,这些物体或物体与另一个物体处于相同的方向。 这意味着他们不必每步查询整个几何。

由于Doom的缘故,BSP在游戏引擎中很常见。


分裂你的世界

我们要避免一次加载整个地图。 相反,我们只想加载我们需要的部分。

原始PlayStation的各种游戏将使用每个房间的每扇门作为加载点。 应该指出的是,加载是(并将继续)是PlayStation的瓶颈。

但这并不意味着没有巧妙的解决scheme和解决方法。 比如Crash Bandicoot使用了狭窄而曲折的道路,这就隐藏了一个事实,那就是只有靠近玩家的物体才会被装载,因为path经常扭曲,并且保持玩家看到的距离有限。

任天堂64有一个不同的约束。 即使有更好的加载速度,地图的大小也有一个上限。 例如,马里奥64负担不起一个大的开放世界。 相反,世界被划分在墙壁上的图画中,每个图像的大小都被控制住了。

在某些地方,同样考虑了塞尔达:时之笛(这将被限制在海尔勒城堡,你可以在墙上input图片)。 幸运的是,引擎的改进允许更大的地图,但区域之间仍然存在负载点。

最后考虑一下旧的GTA游戏,它将地图分成较小的一个。 GTA副城有两个主要的岛屿分开装载,当玩家从一个到另一个有一个负载屏幕…从一个城市另一个是可见的距离,但这只是一个低多边形模型。


certificate负载

现在考虑我的世界。 尽管外观不太好,但它有很高的多边形数量(考虑所有立方体的所有三角形几乎是无尽的地图,也就是很多顶点)。 它如何处理它们? 那么他们被加载在大块,引擎只发送到GPU附近的玩家的大块。

如果您尝试使用“Minecraft”的渲染距离和其他graphics选项,或者由于未能加载的块,您可能会发现自己正在寻找虚空(实际上就是天空盒),在那里应该有土地。


详细程度

GTA圣安地列斯没有负载屏幕分割地图,他们是怎么做的? 他们使用LOD(详细程度)… GTA圣安地列斯工作在一个完整的游戏世界(包括道路和建筑物)的低多边形模型,总是加载,然后其他模型加载在它的顶部(包括道路和再次建设)。 当他们靠近相机时,模型被更高层次的细节所取代。

这意味着如果你移动得足够快(或者你的电脑足够慢),你可以赶上模型正在加载的边缘……但是,由于基本模型总是在那里,你总是会看到道路和原油版本的建筑,而不是空白。


这是最先进的技术(加上针对特定情况和我不知道的任何专有algorithm的任何自定义优化)。 这些技术除了GPU硬件的进步外,还可以在GTA,Skyrim,Red Dead Redemption,Wild Breath等等中find巨大的地图。

PS OpenGL? 不是一个游戏引擎。