假设我们要在场景中移动,那么问题来了。如果我们要移动视线,或者移动相机到另一个位置,或者让整个世界围着相机移动。在计算机的世界里,移动整个世界更容易一点,所以我们就这样做,让相机固定不动。模型-视图矩阵(modelview matrix)是一个4x4矩阵,可以用来移动世界中的每一个点,然后让相机固定不动。这个矩阵基本上就是一系列旋转、位移、缩放的集合。我们在世界坐标系中将点和模型-视图矩阵相乘,这将使我们进入观察坐标系(viewing coordinates)。
裁剪坐标系——只绘制能看到的
这个坐标系有点不同,因为它是左手坐标系(在此之前我们一直使用的右手坐标系),而且是从我们之前定义的视锥体映射到一个x,y,z范围都在(-1,1)之间的正方体。
到现在为止,我们一直追踪场景中的所有点。然而,一旦进入裁剪空间,我们就可以开始裁掉一部分了。还记得坐标从4D到3D的转换吗?我们曾说过,[x,y,z,w]4D=[x/w,y/w,z/w]3D。因为我们只需要位于视锥范围以内的点,我们接下来只需处理符合?1≤x/w≤1或?w≤x≤w的点即可。y和z坐标也一样。这是一个简单的办法分辨一个点是否位于我们视野之内。
如果某些点位于视锥体内,我们对它们执行透视出发(perspective divide),对每个坐标除以w来将其从4D坐标转换成3D坐标。这些点还是位于左手裁剪坐标系中,但是到了这个阶段,我们称其为规格化设备坐标(normalized device coordinates)。
规格化设备坐标系——计算遮挡关系
你可以把这个想成映射到图像的中间步骤。想象一下所有可能的图像大小,我们并不想渲染成一张图片然后进行各种缩放或拉伸或当图像大小发生改变时重新渲染。规格化设备坐标(NDC)很有用,因为无论图片最终大小是多少,你可以在NDC里面针对性的进行合适的缩放。在NDC里你将看到图片如何被构造。被渲染的图像是视锥体里的物体在近裁剪面上的投影。因此,一个点在Z轴上的值越小,这个点就越近。
这个阶段,通常我们不再进行矩阵计算,而是应用一个视窗变换。这通常只是拉伸坐标来适应视窗,或最终图像大小。最后一步是通过转换坐标到窗口坐标来绘制图像。
窗口坐标系——将物体缩放到画布
窗口是图像最终被绘制的地方。在这里,我们的3D世界呈现为近裁剪面上的一张2D图像。我们可以使用一系列的线条和多边形算法来绘制最终图像。此时,一些2D效果,如抗锯齿和多边形裁剪,在图片被被绘制之前执行。
然而,窗口可能有不同的坐标系统。比如,有时图片基于向右为X+,向下为Y+绘制。为了正确绘制图片,有时候可能需要做一些转换。
又回来了——图形渲染管线
上述步骤你不用都亲历亲为。某种程度上,你会使用图形渲染库来定义诸如模型视图矩阵、投影矩阵以及世界坐标系中的多边形之类的东西,渲染库会搞定一切。如果你在设计一个游戏,你不需要在意多边形是如何被绘制的,只需确保它们执行的正确又快速,对吗?
OpenGL和DirectX之类的库效率很高,而且能够有效利用精密的图形硬件来简单又快速的执行这些计算。它们广泛使用,所以最好适应它们。它们还给你留下很大空间来自定义一些事情,你会为你能做到的某些事感到惊讶的!
结论
这是一个关于图形学理论的简单概览。渲染过程中后续还有很多步骤发生,但是这应该能给你一个大致的方向,让你在阅读其它文章或论坛里的相关技术时能够理解的更好。
外部链接