2013-07-14 57 views
1

就像我受虐狂一樣,我試圖學習創建模型視圖和透視矩陣後面的所有矩陣數學,這樣我就可以編寫自己的函數來生成它們而不使用JS庫。學習WebGL背後的數學

我理解矩陣的概念,但不知道如何實際生成它們。我在glMatrix圖書館一直在尋找非常密切的,我有以下問題:

1)在以下mat4.perspecive方法到底是怎麼回事?

/** 
* Generates a perspective projection matrix with the given bounds 
* 
* @param {mat4} out mat4 frustum matrix will be written into 
* @param {number} fovy Vertical field of view in radians 
* @param {number} aspect Aspect ratio. typically viewport width/height 
* @param {number} near Near bound of the frustum 
* @param {number} far Far bound of the frustum 
* @returns {mat4} out 
*/ 
mat4.perspective = function (out, fovy, aspect, near, far) { 
    var f = 1.0/Math.tan(fovy/2), 
     nf = 1/(near - far); 
    out[0] = f/aspect; 
    out[1] = 0; 
    out[2] = 0; 
    out[3] = 0; 
    out[4] = 0; 
    out[5] = f; 
    out[6] = 0; 
    out[7] = 0; 
    out[8] = 0; 
    out[9] = 0; 
    out[10] = (far + near) * nf; 
    out[11] = -1; 
    out[12] = 0; 
    out[13] = 0; 
    out[14] = (2 * far * near) * nf; 
    out[15] = 0; 
    return out; 
}; 

具體來說,我得到什麼Math.tan(fovy/2)的計算,但爲什麼要採取它的逆?同樣,爲什麼取近邊界和遠邊界的差值的倒數?此外,爲什麼out[11]設置爲-1以及out[14]中存儲的值是多少?

2)庫中的以下mat4.lookAt方法也困惑我:

/** 
* Generates a look-at matrix with the given eye position, focal point, 
* and up axis 
* 
* @param {mat4} out mat4 frustum matrix will be written into 
* @param {vec3} eye Position of the viewer 
* @param {vec3} center Point the viewer is looking at 
* @param {vec3} up vec3 pointing up 
* @returns {mat4} out 
*/ 
mat4.lookAt = function (out, eye, center, up) { 
    var x0, x1, x2, y0, y1, y2, z0, z1, z2, len, 
     eyex = eye[0], 
     eyey = eye[1], 
     eyez = eye[2], 
     upx = up[0], 
     upy = up[1], 
     upz = up[2], 
     centerx = center[0], 
     centery = center[1], 
     centerz = center[2]; 

    if (Math.abs(eyex - centerx) < GLMAT_EPSILON && 
     Math.abs(eyey - centery) < GLMAT_EPSILON && 
     Math.abs(eyez - centerz) < GLMAT_EPSILON) { 
     return mat4.identity(out); 
    } 

    z0 = eyex - centerx; 
    z1 = eyey - centery; 
    z2 = eyez - centerz; 

    len = 1/Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2); 
    z0 *= len; 
    z1 *= len; 
    z2 *= len; 

    x0 = upy * z2 - upz * z1; 
    x1 = upz * z0 - upx * z2; 
    x2 = upx * z1 - upy * z0; 
    len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2); 
    if (!len) { 
     x0 = 0; 
     x1 = 0; 
     x2 = 0; 
    } else { 
     len = 1/len; 
     x0 *= len; 
     x1 *= len; 
     x2 *= len; 
    } 

    y0 = z1 * x2 - z2 * x1; 
    y1 = z2 * x0 - z0 * x2; 
    y2 = z0 * x1 - z1 * x0; 

    len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2); 
    if (!len) { 
     y0 = 0; 
     y1 = 0; 
     y2 = 0; 
    } else { 
     len = 1/len; 
     y0 *= len; 
     y1 *= len; 
     y2 *= len; 
    } 

    out[0] = x0; 
    out[1] = y0; 
    out[2] = z0; 
    out[3] = 0; 
    out[4] = x1; 
    out[5] = y1; 
    out[6] = z1; 
    out[7] = 0; 
    out[8] = x2; 
    out[9] = y2; 
    out[10] = z2; 
    out[11] = 0; 
    out[12] = -(x0 * eyex + x1 * eyey + x2 * eyez); 
    out[13] = -(y0 * eyex + y1 * eyey + y2 * eyez); 
    out[14] = -(z0 * eyex + z1 * eyey + z2 * eyez); 
    out[15] = 1; 

    return out; 
}; 

mat4.perspecive方法類似的,爲什麼被計算出的矢量的長度的倒數?此外,爲什麼該值然後乘以z0,z1z2值?對於變量x0-x2變量和y0-y2變量也做同樣的事情。爲什麼?最後,爲out[12] - out[14]設置的值的含義是什麼?

3)最後,我有幾個關於mat4.translate方法的問題。具體來說,我買了這本書Professional WebGL Programming: Developing 3D Graphics for the Web,和它說,下面的4×4矩陣被用來轉換頂點:

1 0 0 x 
0 1 0 y 
0 0 1 z 
0 0 0 1 

然而,當我看到在glMatrix庫中的以下mat4.translate方法,我看到out[12] - out[15]通過一些複雜的方程來設置。爲什麼這些價值觀設置?

/** 
* Translate a mat4 by the given vector 
* 
* @param {mat4} out the receiving matrix 
* @param {mat4} a the matrix to translate 
* @param {vec3} v vector to translate by 
* @returns {mat4} out 
*/ 
mat4.translate = function (out, a, v) { 
    var x = v[0], y = v[1], z = v[2], 
     a00, a01, a02, a03, 
     a10, a11, a12, a13, 
     a20, a21, a22, a23; 

    if (a === out) { 
     out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; 
     out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; 
     out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; 
     out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; 
    } else { 
     a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; 
     a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; 
     a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; 

     out[0] = a00; out[1] = a01; out[2] = a02; out[3] = a03; 
     out[4] = a10; out[5] = a11; out[6] = a12; out[7] = a13; 
     out[8] = a20; out[9] = a21; out[10] = a22; out[11] = a23; 

     out[12] = a00 * x + a10 * y + a20 * z + a[12]; 
     out[13] = a01 * x + a11 * y + a21 * z + a[13]; 
     out[14] = a02 * x + a12 * y + a22 * z + a[14]; 
     out[15] = a03 * x + a13 * y + a23 * z + a[15]; 
    } 

    return out; 
}; 

謝謝大家的時間,並對所有的問題抱歉。我來自JS背景,而不是OpenGL/3D編程背景,所以我很難理解所有矩陣背後的數學。

如果有任何很好的資源可以解釋這些方程/方法所使用的數學方法,那麼這也很棒。謝謝。

回答

3

具體來說,我得到Math.tan(fovy/2)正在計算什麼,但是爲什麼 取反了呢?

因爲焦距d來自公式

Math.tan(fovy/2) = y/d 

得到你需要通過

1/Math.tan(fovy/2) 

繁殖爲什麼採取之間的差的倒數焦距近邊界和 遠邊界?另外,爲什麼out [11]設置爲-1,以及存儲在[14]中的值 爲什麼?

您可以使用焦距d項目(x,y,z)(x*d/z, y*d/z)。這是足夠的OpenGL但需要一個線性變換(x,y,z)例如投影給出座標[-1,1]。這種標準化的座標簡化了剪切並保留用於移除隱藏表面的z信息。

出[11]被設置爲-1,因爲沒有,除非施加一個反射給出歸一化座標的線性變換。這個-1導致系統的旋向性以標準化的座標切換。

出[14]使用具有出[10]從[-n -f]至[-1 1]後投影變換ž。

與mat4.perspecive方法類似,爲什麼要計算向量長度的倒數 ?此外,爲什麼該值然後乘以z0,z1和z2值 ?對於x0-x2變量和y0-y2變量, 也是一樣的。爲什麼?

爲了標準化矢量x,y和z

什麼是出[12]中設置的值的含義-out [14]?

的照相機是由矢量和位置的基礎的。 輸出[12] - 輸出[14]應用反轉換來設置攝像機位置。

然而,當我看在 glMatrix庫中的以下方法mat4.translate,我看到了[12] -out [15]通過一些複雜 方程組。爲什麼這些價值觀設置?

的公式看起來複雜,因爲它是一個平移矩陣的產品,現有的矩陣a

專業WebGL的編程:開發3D網頁圖形

我不知道這本書,這或許可以解釋一些數學,但如果你需要詳細的解釋,你應該考慮埃裏克·倫蓋爾的book解釋和派生出3D光柵圖形中使用的重要數學。

+0

一個。拉斯拉姆,非常感謝你的詳細解答。爲了澄清,如果'Math.tan(fovy/2)= y/d',那麼'1/Math.tan(fovy/2)'不等於'd/y',而不僅僅是'd'?另外,我很抱歉,但我很難理解'd'是什麼。我在想'd'和'z'是一樣的,但是'd/z'總是'1'。你能解釋我在這裏失蹤的事嗎?另外,你的意思是什麼:'相機是由矢量和位置的基礎組成的?非常感謝。你提出的這本書聽起來很有趣,但根據一些評論,我擔心它會引起更多混淆。 – HartleySan

+0

「d = y/Math.tan(fovy/2)」這意味着你放入矩陣的因子是「1/Math.tan(fovy/2)」。當您將矩陣乘以一個向量「y/Math.tan(fovy/2)」時,會出現。 d是焦距。它是表示從觀看者到近平面的距離的常量。相機空間由仿射幀定義:三個基向量x,y,z和位置「眼睛」。我強烈推薦這本書:並非所有書籍都描述瞭如何在OpenGL –

+0

的背景下逐步獲得這些矩陣,但我仍然有點困惑,但是你已經把書賣給了我。另外,非常感謝您的解釋。我理解他們中的大多數,但我想這只是其中很難解釋的事情之一。謝謝。 – HartleySan