50

当您学习 3D 编程时,您会被告知用 3 个转换矩阵来思考是最简单的:

  1. 模型矩阵。该矩阵对每个模型都是独立的,它会根据需要旋转和缩放对象,最后将其移动到 3D 世界中的最终位置。“模型矩阵将模型坐标转换为世界坐标”。

  2. 视图矩阵. 对于大量对象(如果不是全部对象),该矩阵通常是相同的,并且它根据当前的“相机位置”旋转和移动所有对象。如果您想象 3D 场景是由摄像机拍摄的,并且屏幕上呈现的是该摄像机捕获的图像,则摄像机的位置及其观察方向定义了场景的哪些部分是可见的以及对象如何出现在拍摄的图像上。在渲染单个帧时更改视图矩阵的原因很少,但实际上确实存在(例如,通过两次渲染场景并更改其间的视图矩阵,您可以在场景中创建一个非常简单但令人印象深刻的镜子) . 通常,视图矩阵在绘制的两个帧之间只改变一次。"

  3. 投影矩阵。投影矩阵决定了如何将这些 3D 坐标映射到 2D 坐标,例如,是否应用透视(对象离观察者越远越小)或不应用透视(正交投影)。投影矩阵几乎从未改变。如果您正在渲染到一个窗口并且窗口大小已更改,或者您正在渲染全屏并且分辨率已更改,则它可能必须更改,但前提是新窗口大小/屏幕分辨率具有与以前不同的显示宽高比。有一些疯狂的效果,你可能想改变这个矩阵,但在大多数情况下,它在你的程序的整个生命周期中几乎是恒定的。“投影矩阵将眼睛坐标转换为屏幕坐标”。

这对我来说很有意义。当然,总是可以将所有三个矩阵组合成一个矩阵,因为先将向量乘以矩阵A然后乘以矩阵B与将向量乘以矩阵相同C,其中C = B * A

现在,如果您查看经典的 OpenGL(OpenGL 1.x/2.x),OpenGL 知道投影矩阵。然而 OpenGL 不提供模型或视图矩阵,它只提供组合的模型视图矩阵。为什么?这种设计迫使您永久保存和恢复“视图矩阵”,因为它会被应用于它的模型转换“破坏”。为什么没有三个独立的矩阵?

如果您查看新的 OpenGL 版本(OpenGL 3.x/4.x)并且您不使用经典渲染管道而是使用着色器(GLSL)自定义所有内容,那么根本就没有可用的矩阵,您必须定义自己的矩阵。大多数人仍然保留投影矩阵和模型视图矩阵的旧概念。为什么要这么做?为什么不使用三个矩阵,这意味着您不必永久保存和恢复模型视图矩阵,或者您使用单个组合模型视图投影 (MVP) 矩阵,这可以节省您在顶点着色器中的矩阵乘法永远呈现单个顶点(毕竟这样的乘法也不是免费的)。

所以总结一下我的问题:与拥有三个单独的矩阵或单个 MVP 矩阵相比,将模型视图矩阵与单独的投影矩阵组合在一起的优势是什么?

4

3 回答 3

40

实际看一下。首先,您发送的矩阵越少,与位置/法线/等相乘的矩阵就越少。因此,您的顶点着色器越快。

所以第 1 点:矩阵越少越好。

但是,您可能需要做某些事情。除非您正在进行 2D 渲染或一些简单的 3D 演示应用程序,否则您将需要进行照明。这通常意味着您需要将位置和法线转换为世界或相机(视图)空间,然后对它们进行一些光照操作(在顶点着色器或片段着色器中)。

如果你只从模型空间到投影空间,你就不能这样做。您不能在投影后空间中进行照明,因为该空间是非线性的。数学变得复杂得多。

所以,第 2 点:您需要在模型和投影之间至少停留一站。

所以我们至少需要2个矩阵。为什么是模型到相机而不是模型到世界?因为在着色器的世界空间中工作是个坏主意。您可能会遇到与远离原点的翻译相关的数值精度问题。然而,如果您在相机空间中工作,则不会遇到这些问题,因为没有任何东西离相机太远(如果是,它可能应该在远深度平面之外)。

因此:我们使用相机空间作为照明的中间空间。

于 2012-05-16T11:52:51.270 回答
2

在大多数情况下,您的着色器将需要世界或眼睛坐标中的几何图形进行着色,因此您必须将投影矩阵与模型矩阵和视图矩阵分开。

让着色器将几何体与两个矩阵相乘会损害性能。假设每个模型都有千(或更多)个顶点,那么在 cpu 中计算一次模型视图矩阵会更有效,并让着色器少做一次矩阵向量乘法。

于 2012-05-16T11:47:18.150 回答
0

我刚刚通过分离投影矩阵解决了一个 z 缓冲区冲突问题。GPU 负载没有明显增加。以下两张截图显示了两种结果——注意绿色和白色层的战斗。

连接矩阵 单独投影

于 2021-09-16T12:20:53.427 回答