原文地址:http://www.songho.ca/opengl/gl_normaltransform.html
几点说明
- OpenGL的矩阵变换中,矩阵左乘向量。
- 向量的点成可以看成是特殊的矩阵相乘,例如Vector3 * Vector3可以看成1x3的矩阵(行向量)乘以3x1的矩阵(列向量),得到一个标量
- 矩阵的相乘满足结合律,因此矩阵和向量的相乘过程也可以使用结合律。
法线变换
当在OpenGL中开启了光照,法线向量被用来决定在特定的顶点或者表面需要接收多少光照亮。光照的处理是在眼睛坐标系空间的。所以在模型(本地)坐标系的法线向量也需要通过 GL_MODELVIEW 矩阵转换到眼睛坐标系。
然而,法线向量的转换方式与顶点不同。我们不能简单将GL_MODELVIEW矩阵与法线相乘。
考虑一个法线向量(1,0,0)和一个顶点(0,0,0).。如果GL_MODELVIEW矩阵只是简单的沿着Y轴方向平移了2个单位,顶点的坐标会是(0,2,0),然而法线应该保持 (1,0,0) 而不是通过 GL_MODELVIEW 矩阵变换后的(1,2,0)。
法线和平面方程
为了理解法线向量是如何转换到视图空间(眼睛空间)的,把法线看成是平面方程的系数,法线与该平面垂直。
假设一个三角形的顶点为V1-V2-v3,该三角形所在平面的其次平面的法线是n=(nx,ny,nz,nw)。
如果我们把这个三角形看成是其次空间的平面,那么它的平面方程就是:
nx * x + ny * y + nz * z+ nw * w = 0
因为3个顶点都在这个平面上,因此我们把这些顶点带入到平面方程都是成立的。
该平面方程等价的矩阵形式是:
这个平面方程是将法线的转置和顶点进行相乘。
现在令矩阵 M = GL_MODELVIEW,我们在上面的等式中插入 inverse(M) * M操作,下面的方程与上面的等价,因为inverse(M) * M为单位矩阵(向量看成矩阵,矩阵满足结合律)。
变换后的平面方程和法线变换矩阵
正如你看到的,上面的等式中右边部分Mv是把顶点转换到视图空间,因为平面方程也被转换了,那么左边部分就应该是视图空间的法线向量了。可以这么理解:转换后的的顶点Mv在转换后的视图空间的平面中。
因此,通过 GL_MODELVIEW矩阵M我们就可以把法线从物体空间转换到视图空间。
或者,通过把顶点的前向相乘转化为后置相乘,我们得到:
法线变换矩阵的通用求法
上面求法线从模型空间到视图空间的变换矩阵的推导方式可以用于其他的空间变换中,只要M是对应顶点变换矩阵就可以了。比如我们要获得法线从模型空间到世界空间的变换矩阵,我们只需要令M为顶点的从模型空间到世界空间的变换矩阵,那么法线变换矩阵就是M矩阵的逆的转置。