三維投影變換是3D固定流水線的重要組成部分,是將相機空間中的點從視錐體(frustum)變換到規則觀察體(Canonical View Volume,CVV)中,待裁剪完畢後進行透視除法的行爲。在算法中它是通過透視矩陣乘法和透視除法兩步完成的。通過投影,幾何圖形的3D座標轉換成屏幕上的2D座標。通過指定投影,可以指定在窗口中顯示的視景體(Viewing Volume),並指定如何對其進行變換。
正投影(Orthographic Projection)
又稱平行投影,使用這種投影需要指定一個正方形或長方形的視景體,視景體之外的任何物體將被裁剪掉,不會被繪製。所有實際大小相同的物體在屏幕上都有相同的大小,不管遠近。
public array orthographic_matrix(float l, float r, float t, float b, float n, float f)
{
vector4 row0 = vector4( 2/(r-l), 0, 0, (l+r)/(l-r) );
vector4 row1 = vector4( 0, 2/(t-b), 0, (b+t)/(b-t) );
vector4 row2 = vector4( 0, 0, 2/(f-n), (n+f)/(n-f) );
vector4 row3 = vector4( 0, 0, 0, 1 );
return matrix_4(row0, row1, row2, row3);
}
透視投影(Perspective Projection)
在這種投影中,遠處的物體看上去比近處的物體更小一些。它的視景體看上去像一個頂部被削平的金字塔,叫平截頭體(frustum),觀察方向從金字塔的尖端到寬闊端,觀察者的視點與金字塔的尖端拉開一定距離。
public array perspective_matrix(float fov, float aspect, float n, float f)
{
float cot = 1/math.tan(fov/2);
vector4 row0 = vector4( cot/aspect, 0, 0, 0 );
vector4 row1 = vector4( 0, cot, 0, 0 );
vector4 row2 = vector4( 0, 0, (f+n)/(f-n), 2*f*n/(n-f) );
vector4 row3 = vector4( 0, 0, 1, 0 );
return matrix_4(row0, row1, row2, row3);
}
透視投影是非線性變換,光柵化過程中對紋理座標的插值不能使用線性插值,要使用透視校正插值進行計算。
參考資料
OpenGL學習腳印: 投影矩陣和視口變換矩陣(math-projection and viewport matrix)