glsl The gl_NormalMatrix 方向向量的轉換

來源:互聯網
上載者:User
GLSL Tutorial

The gl_NormalMatrix

The gl_NormalMatrix is present in many vertex shaders. In here some light is shed on what is this matrix and what is it for. This section was inspired by the excellent book by Eric Lengyel "Mathematics for 3D Game Programming and Computer Graphics".

Many computations are done in eye space. This has to do with the fact that lighting needs to be performed in this space, otherwise eye position dependent effects, such as specular lights would be harder to implement. //很多計算都是在眼座標中進行的

Hence we need a way to transform the normal into eye space. To transform a vertex to eye space we can write: //因此需要把頂點轉找到眼座標中

vertexEyeSpace = gl_ModelViewMatrix * gl_Vertex;

So why can't we just do the same with a normal vector? First a normal is a vector of 3 floats and the modelview matrix is 4x4. This could be easily overcome with the following code:

//但為什麼不能直接轉換方向向量呢?因為方向向量只有三個分量,但我們可以用下面的代碼解決
normalEyeSpace = vec3(gl_ModelViewMatrix * vec4(gl_Normal,0.0));

So, gl_NormalMatrix is just a shortcut to simplify code writing? No, not really. The above line of code will work in some circunstances but not all. //上面的代碼並不是在所有的情況下都完全正確,我們從下面看一下存在的潛在問題

Lets have a look at a potential problem:

In the above figure we see a triangle, with a normal and a tangent vectors. The following figure shows what happens when the modelview matrix contains a non-uniform scale.
顯示了一個三角形,並且法線垂直於平面,顯示法線經過非均衡縮放後,法線不再垂直平面了

Note: if the scale was uniform, then the direction of the normal would have been preserved, The length would have been affected but this can be easily fixed with a normalization.
//如果x,y,z三個方向縮放比例相同的話,雖然法線向量的長度改變了,但是方向不變,這種情況是可以用單位化向量的方法解決

In the above figure the modelview matrix was applied to all the vertices as well as to the normal and the result is clearly wrong: the normal is no longer perpendicular to the surface.

So now we know that we can't apply the modelview in all cases to transform the normal vector. The question is then, what matrix should we apply?

We know that, prior to the matrix transformation T.N = 0, since the vectors are by definition perpendicular. We also know that after the transformation N'.T' must remain equal to zero, since they must remain perpendicular to each other. Let's assume that the matrix G is the correct matrix to transform the normal vector. T can be multiplied safely by the upper left 3x3 submatrix of the modelview (T is a vector, hence the w component is zero). This is because T can be computed as the difference between two vertices, therefore the same matrix that is used to transform the vertices can be used to transform T. Hence the following equation: 轉換後的兩個向量的點乘應該為0,矩陣G是未知數,是假設的正確的矩陣,M就是頂點的轉換矩陣,也就是模型視圖矩陣,而向量N和T是轉換前的平面的法向量和切向量.

 

The dot product can be transformed into a product of vectors, therefore:
由於GN相乘的結果是向量,因此GN等於GN的轉置(一個向量和它的轉置相同)

Note that the transpose of the first vector must be considered since this is required to multiply the vectors. We also know that the transpose of a multiplication is the multiplication of the transposes, hence:
GN乘積的轉置等於它們轉置的乘積
 

We started by stating that the dot product between N and T was zero, so if the following equation is true then we are on the right track.
由於上式結果為0,因此下式成立(可用反證法,如果下式結果不為單位陣,則上式必不為0向量)

Applying a little algebra yieds
下式由上式進行矩陣運算得到

Therefore the correct matrix to transform the normal is the transpose of the inverse of the M matrix. OpenGL computes this for us in the gl_NormalMatrix.

In the beginning of this section it was stated that using the modelview matrix would work in some cases. Whenever the 3x3 upper left submatrix of the modelview is orthogonal we have:

This is because with an orthogonal matrix, the transpose is the same as the inverse. So what is an orthogonal matrix? An orthogonal matrix is a matrix where all columns/rows are unit length, and are mutually perpendicular. This implies that when two vectors are multiplied by such a matrix, the angle between them after transformation by an orthogonal matrix is the same as prior to that transformation. Simply put the transformation preserves the angle relation between vectors, hence normals remain perpendicular to tangents! Furthermore it preserves the length of the vectors as well.

So when can we be sure that M is orthogonal? When we limit our geometric operations to rotations and translations, i.e. when in the OpenGL application we only use glRotate and gl_Translate and not glScale. These operations guarantee that M is orthogonal. Note: gluLookAt also creates an orthogonal matrix!
//--補充
模型視圖變化只有平移,旋轉的時候才形成正交矩陣,這個時候向量的轉換矩陣就是模型視圖矩陣,而如果變換包括了平移的時候,則向量的轉換矩陣是它的逆的轉置

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.