关于normal在eye坐标系下的变化

参考资料:http://www.lighthouse3d.com/opengl/glsl/index.php?normalmatrix

由于需要在视觉空间进行大量的计算, 所以光照需要在视觉空间中进行计算.
因此我们需要求出视觉空间中的法线向量.
转换一个顶点进入视觉坐标的公式如下:
vertexEyeSpace = gl_ModelViewMatrix * gl_Vertex;
但是为何我们不能够对法线向量做相同的事情呢?
首先, 法线向量是一个拥有三个元素的一维向量, 模型视图矩阵则是4×4矩阵
这点可以用下面的代码轻易解决:
normalEyeSpace = vec3(gl_ModelViewMatrix * vec4(gl_Normal, 0.0));
所以,gl_NormalMatrix仅仅是上面的剪切代码么? 不, 这不是真的. 上面的代码可以用于一些环境, 但不能作用于所有.
让我们看看下面潜在的问题:

在上图我们看到一个三角形, 有一个法线向量和切线向量. 接下来的图显示当一个观察矩阵缩放的时候所显示的情景.(如调用glScale)
如果我们还是调用上面的代码的话.

注意: 当观察矩阵各方向尺寸不一致时,应当预先保存法线的方向, 虽然法线的长度会变化,但是单元化很易修复
在上图, 观察矩阵影响到所有的顶点以及法线. 很明显这个结果是错误的. 法线并不垂直于切线.

所以现在我们得知并不能将观察矩阵应用于所有的法线. 所以我们应当应用怎样的矩阵呢?

注意到T*N = 0. 所以在视觉空间中, 两者还应当是垂直的, 保证转换后的T’*N’ = 0.
假设矩阵G是转换法线N的矩阵.T则乘观察矩阵左上的3*3矩阵M(T是一个向量, 令w为0).式子如下:

点积可以转换成向量积, 如下

由于N”T = 0, 所以我们猜想

(I为单位矩阵)

所以

因此gl_NormalMatrix等于M的逆矩阵的倒置矩阵

在本文的开始曾说模型观察矩阵作用于法线向量有时候也有效, 这是因为观察矩阵为正交矩阵, 即

正交矩阵 —- 任意列/行向量都为单元长度向量. 并相互垂直.
这意味着任意两个向量乘以该向量, 向量间的角度不会发生任何变化.

如果我们仅仅在观察矩阵进行旋转或者移动,我们的当前模型矩阵仍为正交矩阵.
即我们只用glRotate和glTranslate命令,而不用glScale命令.
注意: 我们glLookAt产生的观察模型矩阵也是正交矩阵.

traceback : http://www.cppblog.com/summericeyl/archive/2009/06/24/88411.html

标签:
News, OpenGL

相关日志

If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.

Leave Comment

(必填)

(必填)