2016-04-09 37 views
2

我想創建自己的mvp矩陣作爲練習。透視矩陣背後的數學

auto lookAt(Vec)(const Vec eye, const Vec center, const Vec up) 
if(isVector!Vec && Vec.dimension is 3){ 
    auto z = (eye - center).unit; 
    auto x = cross(up.unit, z); 
    auto y = cross(z, x); 
    alias Mat = Matrix!(Vec.Type, 4, 4); 
    alias Vec4 = Vector!(Vec.Type, 4); 
    return Mat(Vec4(x, 0), 
       Vec4(y, 0), 
       Vec4(z, 0), 
       Vec4(0, 0, 0, 1)) * translate(-eye); 
} 

視圖變換相當簡單,我設置它以便我沿着負Z軸看。

但是我對透視矩陣有一些麻煩。

y' = 1/(tan(fov/2) * z 
x' = 1/(ar * tan(fov/2) * z 

x'y'是新的扭曲的價值觀。所以,我想出了這個矩陣

Mat4f projection(float fov, float ar, float near, float far){ 
    import std.math: tan; 
    auto tanHalfAngle = tan(fov/2.0f); 
    return Mat4f(
     Vec4f(1.0f/(ar * tanHalfAngle) , 0, 0, 0), 
     Vec4f(0, 1.0f/tanHalfAngle, 0, 0), 
     Vec4f(0, 0, 1, 0), 
     Vec4f(0, 0, -1, 0)); 
} 

目前,我只是將它設置,以便Z值始終-1。但是我犯了一個小錯誤,因爲現在除以-Z

事情是矩陣上面的作品。我目前正在渲染一個旋轉的立方體,除了深度值外,一切看起來都正確。

但我真的希望這個矩陣

Mat4f projection(float fov, float ar, float near, float far){ 
    import std.math: tan; 
    auto tanHalfAngle = tan(fov/2.0f); 
    return Mat4f(
     Vec4f(1.0f/(ar * tanHalfAngle) , 0, 0, 0), 
     Vec4f(0, 1.0f/tanHalfAngle, 0, 0), 
     Vec4f(0, 0, -1, 0), 
     Vec4f(0, 0, 1, 0)); 
} 

但多維數據集不顯示在屏幕上的任何更多,我不明白爲什麼。

auto view = lookAt(Vec3f(0, 0, -5), Vec3f(0, 0, 0), Vec3f(0, 1, 0)); 
auto proj = projection(PI/2, 4.0f/3.0f, 0.1f, 100); 

我設置測試值

auto v = proj * view * Vec4f(0.5,0.5,0.5,1); 

這是輸出我在哪裏通過-Z

Vec(-0.375, 0.5, -5.5, 5.5) 
Vec(-0.0681818, 0.0909091, -1) // divided by w 

此劃分第一矩陣得到的是輸出I與第二矩陣獲取我除以Z

Vec(-0.375, 0.5, 5.5, -5.5) 
Vec(0.0681818, -0.0909091, -1) //divided by w 

唯一改變的是標誌。

但是,爲什麼我可以看到第一個矩陣的立方體,但沒有第二個矩陣?

回答

2

的OpenGL默認的剪切規則制定剪裁空間爲滿足下列inequailty所有點趴在視錐內:

-w <= x, y, z <= w 

注意,這個平凡的排除了任何點以w < 0,因爲-w將會>然後,所以它不能被滿足。

視圖轉換相當簡單,我設置它以便我現在沿着負Z軸看。

這不是真的。視圖矩陣並不是而是單獨定義視向,投影矩陣也有影響。當使用標準透視投影時,投影矩陣的最後一行可以簡單地解釋爲投影主軸的方向矢量 - 所以它定義了眼睛空間中的觀察方向矢量。經典GL投影使用(0 0 -1 0),因此-z將成爲觀看方向。

視圖矩陣的工作是放置攝像機和旋轉場景,以便將所插入的世界空間觀察方向映射到投影矩陣使用的眼睛空間觀察方向。

當你翻轉你的投影矩陣除以z而不是-z,這當然意味着它會朝着那個方向看。既然你沒有調整你的視圖矩陣來遵循這個約定,你的相機現在正好在你的視圖矩陣設置的相反方向上查看。位於相機的「前」位置的點數爲z_eye < 0將具有負值w_clip,並被近平面裁剪。