前面两节内容已经说完了所有的三种变换。也就是说我们现在程序里面既不需要glLookAt(),也不需要gluPerspective(),这些矩阵我们都可以自己写。然后,再用glMultMatrix()来调用这些矩阵,注意一点就是OpenGL是左乘,前面给出的矩阵都是右乘矩阵,所以调用的时候需要转置,摆放的位置也要注意。当然,如果用shader的话,这些函数也就用不到了,矩阵顺序也可以自己定义。这里所有的变换都是作用在顶点(Vertex)上的,但是还有一类数据需要进行变换,那就是顶点法线。我们在计算光照的时候,需要在顶点上设置顶点发现,顶点经过各种变换,法线肯定也要跟着变。不过法线的变化跟顶点有些许的不同,本文就介绍下法线变换。
首先,我们需要知道法线的几个注意的地方:
- 法线向量是需要进行归一化的,它的长度必须为1.0。
- 法线向量是表示方向的,跟顶点不一样不是表示位置,所以法线向量只有三个分量,不存在齐次坐标。
- 法线向量的变换中,一般只有旋转变换和部分缩放变换。因为法线向量表示方向,平移后不变化,而且法线如果等轴缩放,归一化后也不变化,另外,法线主要是计算光照,透视变换也用不到。
跟直觉违背的是,法线向量的变换与顶点向量的变换方式是不同的。那么如何变换法线呢?我们首先取出变换矩阵的左上角的3*3矩阵。因为法线向量只需要包含必要的旋转和缩放信息,也可以将物体从模型坐标系变换到眼(相机)坐标系。公式如下:
图1
我们现在现在看看为何需要求逆后转置。如图2所示,我们如果直接将法线向量乘以M,就会出现中间的这种情况,其法线分布明显与表面不垂直,而最右边的图才是正确变换后的法向分布。
图2
我们接下来证明一下公式。这里假设某一点处的法向量为n,切向量为t,由两者在曲面上的垂直关系可知:
图3
假设顶点开始变换,最终的变换矩阵为M,那么变换后的切向量为t'=Mt。切向量可以通过几何分析来验证变换矩阵和顶点是一致的,这里就不详述了。那么我们可以得到变换后的n'和t'之间的关系:
图4
我们根据上式可以得到中间两项GTM=I,所以我们得到最终的发现变换矩阵:
图5
这里就介绍完所有的变换矩阵了,真是一个漫长的过程。其实在这些变换后还有一个视口变换,就是将光栅化后的图像映射到窗口中,但由于这一步时管线内部的操作,这次也就没提了。大家可以试着自己写一下各种矩阵,肯定对OpenGL视图和变换这块更加理解。