計(jì)算三個(gè)點(diǎn)的坐標(biāo)磷支,那么熟悉模型的朋友應(yīng)該知道要有兩個(gè)數(shù)據(jù)谒撼,一個(gè)是頂點(diǎn)坐標(biāo)數(shù)據(jù),一個(gè)是頂點(diǎn)索引數(shù)據(jù)雾狈,在dx11和opengl中廓潜,都會把這兩個(gè)數(shù)據(jù)緩存在硬件緩存區(qū)中,軟件光柵化箍邮,我們拿到這兩個(gè)數(shù)據(jù)茉帅,取出一個(gè)三角形的三個(gè)點(diǎn)的坐標(biāo),通過mvp變換就可以完成坐標(biāo)得一部分轉(zhuǎn)換锭弊,但是還有一部分是什么呢堪澎?如上圖,乘上mvp矩陣后味滞,也就相當(dāng)于完成了投影變換樱蛤,僅此而已钮呀,下邊的步驟一般是硬件為我們完成的,但是軟件光柵化不借助任何gpu昨凡,就cpu爽醋,那就開始一步步算嘛,從裁剪坐標(biāo)系開始吧便脊!
為什么要裁剪坐標(biāo)系蚂四,因?yàn)樵诮仡^體內(nèi)部,有時(shí)候模型在截頭體內(nèi)部放不下哪痰,超出部分需要被剪裁遂赠,這個(gè),過程網(wǎng)上說的各種復(fù)雜晌杰,簡單用代碼來說就是
//檢查齊次坐標(biāo)同 cvv 的邊界用于視錐裁剪
int transform_check_cvv(const vector_t*v) {
????float????w = v->w;
????int????check =0;
????if(v->z<0.0f) check |=1;
????if(v->z>? w) check |=2;
????if(v->x< -w) check |=4;
????if(v->x>? w) check |=8;
????if(v->y< -w) check |=16;
????if(v->y>? w) check |=32;
return????check;
}
在上述代碼中可見跷睦,其實(shí)就是很簡單做了一下判斷是否在截頭體內(nèi)部,一個(gè)三角形可能完全在截頭體內(nèi)部肋演,也可能完全在截頭體外部抑诸,也可能部分在截頭體內(nèi)部,完全在內(nèi)部的不用管嘛爹殊,但是完全在外邊的需要剔除蜕乡,部分在截頭體外部的,需要舍去在外部的部分边灭,重新把在內(nèi)部的部分進(jìn)行分割成兩個(gè)三角形再次進(jìn)行處理异希。
PS:當(dāng)然上邊代碼只是簡單判斷下一個(gè)點(diǎn)是否在三角形內(nèi)部啦,代碼來自韋易笑大神
好了裁剪完了绒瘦,就開始下一步進(jìn)行透視除法嘍称簿,就是把一個(gè)點(diǎn)的(x, y, z, w)都除以w變成(x/w, y/w, z/w, 1)變成ndc中的坐標(biāo),
簡單來說就是照著做就完事了惰帽,復(fù)雜來說憨降,去看龍書有具體為什么這么做。该酗。授药。(當(dāng)然我寫這個(gè)只是為了初學(xué)者腦子里有個(gè)大體步驟思路,不深究呜魄,容易帶丟了給)
下邊是視口變換原理推導(dǎo)悔叽,簡單來說就是ndc變換到屏幕上的坐標(biāo)
其中
ndc的坐標(biāo)范圍是
而viewport的坐標(biāo)范圍是
注:由上圖知,視口的起點(diǎn)為(X, Y)爵嗅,寬高分別為Width和Height娇澎,x軸向右為正,y軸向下為正睹晒,y軸的方向與三維坐標(biāo)正好相反趟庄。視口是一個(gè)2D平面括细,但是在viewport變換中,Z坐標(biāo)也是跟著變換的戚啥,只是在這個(gè)圖中沒有體現(xiàn)奋单。
先求變換矩陣的第一列
ndc中的左上角點(diǎn)(-1, 1, 0, 1)映射到viewport中的起點(diǎn)(X, Y, MinZ, 1),
ndc中的右上角點(diǎn)(1, 1, 0, 1)映射到viewport中的點(diǎn)(X+Width, Y, MinZ, 1),
假設(shè)變換矩陣的第一列為[x’, y’, z’, 1]T據(jù)矩陣乘法有
[-1, 1, 0, 1]* [x’, y’, z’, 1]T?= X
[1, 1, 0, 1]* [x’, y’, z’, 1]T?= X+Width
對應(yīng)的兩個(gè)方程為
-1*x’ + 1*y’ + 0*z’ + 1*w’ = X
1*x’ + 1*y’ + 0*z’ + 1*w’ = X+Width
解之得
x’ = Width/2
y’ = 0
z’ = 0
w’ = x + Width/2
再求第二列
列方程(這里省略了x’,z’,但結(jié)果不變猫十,下同)
y’ + 1*w’=Y
-1*y’ + 1*w’=Y+Height
解之得
y’ = -Height/2
w’ = Y + Height/2
最后求第三列
列方程
0*z’ + 1*w’ = MinZ
1*z’ + 1*w’ = MaxZ
解之得
z’ = MaxZ – MinZ
w’ = MinZ
組合以上各列览濒,得到視口變換矩陣
然后 嘿嘿嘿,坐標(biāo)算出來了l挪省X移摺P醵獭江兢!