为什么有一个单独的投影矩阵,同时结合模型和视图矩阵是有益的?

Mec*_*cki 48 opengl glsl

当您学习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矩阵的情况下,哪个优势具有组合的模型 - 视图矩阵以及单独的投影矩阵?

Nic*_*las 38

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

所以第1点:更少的矩阵更好.

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

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

所以,第2点:你需要在模型和投影之间至少停留一次.

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

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

  • @Ian:那是胡说八道; 没有特殊的矩阵 - 矩阵乘法硬件.4x4*4x4乘法需要16个周期.但这很好,因为你无论如何都不需要这样做.如果你只是转换矢量(位置或方向),那么你只需要进行矩阵/向量乘法,这需要4个周期. (4认同)
  • 照明,当然!我根本没想过照明.这可能是因为我从未编写过自己的着色器,可以执行任何照明.你不能再在投影空间做照明似乎是合乎逻辑的. (3认同)