作者简介姜雪伟,泰课在线高级讲师·海洋

经过投影矩阵的变换后,接下来开始进行裁剪操作了,当完成所有的裁剪工作后,就需要进行真正的投影了,也就是说需要把视锥体投影到屏幕空间中,屏幕空间是一个二维空间,因此,必须把顶点从裁剪空间投影到屏幕空间中,生成对应的2D坐标。这个过程需要两个步骤。

首先,需要进行标准齐次除法,也称为透视除法,就使用齐次坐标系的w分量去除以x,y,z分量。在OpenGL中,我们把这一步得到的坐标叫做归一化的设备坐标(NDC),这个在以前的博客中有所介绍。不理解的读者可以去翻阅以前的博文,经过这一步,可以把坐标从齐次裁剪坐标空间转换到NDC中。经过透视投影变换后的裁剪空间,进过齐次除法后会变换到一个立方体内。按照OpenGL的传统,这个立方体的x,y,z分量的范围都是[-1,1]。但是在DirectX中,z的分量范围是[0,1]。而Unity选择了OpenGL这样的齐次裁剪空间。如下图所示:

泰课在线

而对于正交投影来说,它的裁剪空间实际已经是一个立方体了,而且由于经过正交投影矩阵变换后的顶点w分量是1,因此齐次除法并不会对顶点的x,y,z坐标产生影响,如下图所示:

经过齐次除法后,透视投影和正交投影的视锥体都变换到一个相同的立方体内。现在,我们可以根据变换后的x和y坐标来映射输出窗口的对应像素坐标。

在Unity 中,屏幕空间中左下角的像素坐标是(0,0),右上角的像素坐标是(pixelWidth,pixelHeight),由于当前的x和y坐标都是[-1,1],因此映射的过程就是一个缩放的过程。

齐次除法和屏幕映射的过程可以使用下面的公式来表示:

泰课在线

Unity中,从裁剪空间到屏幕空间的转换是由Unity帮我们完成的,我们的顶点着色器只需要把顶点转换到裁剪空间即可。在前面步骤中,我们知道了裁剪空间中模型的孩子位置-(11.691,15.311,23.692,27.31)。接下来确定模型的孩子节点在屏幕上的像素位置。假设,当前屏幕的像素宽度为400,高度为300。首先,我们需要进行齐次除法,把裁剪空间中的坐标投影到NDC中,然后再映射到屏幕空间中。过程如下:

泰课在线

这样就可以得到模型的孩子节点(285.617,234.096)。

总结:

以上就是一个顶点如何从模型空间变换到屏幕空间的过程,以及它们之间的矩阵变换。顶点着色器的最基本任务就是把顶点坐标从模型空间转换到裁剪空间中。而在片元着色器中,通常可以得到该片元在屏幕空间的像素位置。以上只是告诉读者一些最重要的坐标空间,在实际开发中也会遇到,比如切线空间,通常用于法线映射。最后把Unity的各个坐标空间给读者展示如下:

泰课在线