当你学习3D编程时,你会被教导用3个转换矩阵来思考它是最简单的:
模型矩阵。该矩阵对于每个模型都是独立的,它可以根据需要旋转和缩放对象,最后将其移动到3D世界中的最终位置。 “模型矩阵将模型坐标转换为世界坐标”。
查看矩阵。对于大量对象(如果不是对于所有对象),该矩阵通常是相同的,并且它根据当前“摄像机位置”旋转并移动所有对象。如果您对相机拍摄3D场景进行成像,并且屏幕上呈现的内容是此相机捕获的图像,则相机的位置及其查看方向定义场景的哪些部分可见以及对象如何出现在捕获的图像上。在渲染单个帧时更改视图矩阵几乎没有理由,但实际上存在这些原因(例如,通过渲染场景两次并更改其间的视图矩阵,您可以在场景中创建一个非常简单但令人印象深刻的镜像) 。通常,视图矩阵在绘制的两个帧之间仅改变一次。 “视图矩阵将世界坐标转换为眼睛坐标”。
投影矩阵。投影矩阵决定这些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矩阵的情况下,哪个优势具有组合模型视图矩阵和单独的投影矩阵?
答案 0 :(得分:38)
所以第1点:更少的矩阵更好。
但是,您可能需要做某些事情。除非您正在进行2D渲染或一些简单的3D演示应用程序,否则您将需要进行照明。这通常意味着您需要将位置和法线转换为世界或相机(视图)空间,然后对它们进行一些照明操作(在顶点着色器或片段着色器中)。
如果你只是从模型空间到投影空间,你不能这样做。您无法在投影后空间中进行照明,因为该空间是非线性的。数学变得复杂得多。
所以,第2点:你需要在模型和投影之间至少一个停止。
所以我们需要至少2个矩阵。为什么要模型到相机而不是模型到世界?因为working in world space in shaders is a bad idea.您可能会遇到与远离原点的翻译相关的数值精度问题。然而,如果你在相机空间工作,你就不会遇到这些问题,因为没有任何东西离相机太远(如果是的话,它可能应该在远深度平面之外)。
因此:我们使用相机空间作为照明的中间空间。
答案 1 :(得分:2)
在大多数情况下,着色器将需要世界中的几何图形或阴影中的眼睛坐标,因此您必须从模型和视图矩阵中分离投影矩阵。
使着色器将几何体与两个矩阵相乘会损害性能。假设每个模型都有thousends(或更多)顶点,那么在cpu中计算一次模型视图矩阵就更有效了,让着色器做一个较少的mtrix-vector乘法。