原帖地址:http://ogldev.atspace.co.uk/www/tutorial06/tutorial06.html
在這篇教程中,我們開始對三維物體進行位置變化操作,比如平移、旋轉、縮放等等。物體位置變化的操作通常都是通過矩陣來實現的,每種變化用一個矩陣表示,如果一個物體進行多種位置操作,可以把它們對應的矩陣乘起來,最后再乘以頂點的坐標,這樣就可以得到物體位置變化后的頂點坐標位置。
首先我們看下平移操作,平移表示沿着一個任意長度和方向的向量,把物體從一個位置移動到另一個位置。比如我現在要把下圖中左邊的三角形移動到右邊去。
第一種方法就是提供一個偏移向量,在下圖中偏移向量就是(1,1),把該向量作為一個uniform變量傳輸到shader中去,在每個頂點shader操作中,把該向量增加到頂點的位置上。
第二種方法是用一個矩陣表示偏移,然后把該矩陣作為uniform變量,傳輸到shader中去,然后用該矩陣乘以頂點坐標得到偏移后的頂點坐標。
下面我們看下如何得到這個平移矩陣?如下圖,什么樣的矩陣乘以頂點(0,0),得到頂點(1,1),首先2維矩陣是不能做到這點的,同樣的你也不能通過三維矩陣從頂點(0,0,0)得到(1,1,1)。
通常情況下,給定矩陣M,一個頂點P(x,y,z),以及向量V(v1,v2,v3),則有M * P=P1(x + v1, y + v2, z + v3),這意味着矩陣M把頂點P,平移到位置P1,從P1的結果可以看出,它的每個分量是P的每個分量和V的相對應的分量乘積的和。
對於3維向量來說,最終的矩陣M如下圖左邊矩陣,而三維向量(x,y,z)也擴展成了四維向量(x,y,z,1),此時 M*P=P1得以實現。四維向量的第四維稱作w,這種坐標也就齊次坐標,通常對點來說w=1,對向量來說w=0,所以點可以平移,但向量不行。
下面簡單看下程序的代碼:
struct Matrix4f {
float m[4][4];
};
我們在math_3d.h中增加一個4x4的矩陣結構,用來定義物體坐標變化矩陣。
GLuint gWorldLocation;
我們用這個OpenGL句柄訪問shader中的世界變化矩陣uniform變量,之所以叫世界變化矩陣,是因為我們的平移操作時在世界坐標系中進行的。
Matrix4f World;
World.m[0][0] = 1.0f; World.m[0][1] = 0.0f; World.m[0][2] = 0.0f; World.m[0][3] = sinf(Scale);
World.m[1][0] = 0.0f; World.m[1][1] = 1.0f; World.m[1][2] = 0.0f; World.m[1][3] = 0.0f;
World.m[2][0] = 0.0f; World.m[2][1] = 0.0f; World.m[2][2] = 1.0f; World.m[2][3] = 0.0f;
World.m[3][0] = 0.0f; World.m[3][1] = 0.0f; World.m[3][2] = 0.0f; World.m[3][3] = 1.0f;
在渲染函數中,我們定義了世界矩陣,並設置v2和 v3 為0,這樣物體在Y軸和z軸坐標不變,設置v1為sinf函數的結果,它的值在[-1,1]之間變化,則物體的x坐標在[-1,1]之間不斷變化。
glUniformMatrix4fv(gWorldLocation, 1, GL_TRUE, &World.m[0][0]);
這是給第二個uniform變量賦值,它是一個4x4的矩陣。第一個參數是shader uniform變量的位置索引,第二個參數是要更新的矩陣的數量,我們只有一個矩陣,所以其值是1,通過這個參數,我們可以同時給多個矩陣賦值。第三個參數指定矩陣是行主序還是列主序,行主序意思是矩陣在數組中是按一行一行存儲的,列主序則表示矩陣在數組中是一列一列存儲的,c++默認是行主序的,例如下面的二維數組:
int a[2][3];
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1][0] = 4;
a[1][1] = 5;
a[1][2] = 6;
它表示下面的矩陣:
1 2 3
4 5 6
在內存中的存儲方式是:1 2 3 4 5 6
glUniformMatrix4fv()的第三個參數是 GL_TRUE ,因為我們使用行主序。也可以使用列主序,這時表示的是轉置的矩陣。第四個參數矩陣在內存中的起始地址。
下面是shader中的代碼:
uniform mat4 gWorld;
它表示一個4x4的矩陣,在shader中mat2,mat3也可以使用。
gl_Position = gWorld * vec4(Position, 1.0);
三角形頂點的位置屬性是三維向量,但我們在shader中使用四維的齊次坐標,所以我們會擴展位置向量,並設置w=1.0。
程序執行后,每幀都會傳入一個平移世界矩陣,我們用它改變頂點的位置,使得物體x坐標在[-1,1]之間移動。
程序運行后,界面如下,一個三角形在x方向不斷的移來移去: