3D 圖形光柵化的透視校正問題?
最近在做本科畢業設計,想動手寫一個 3D 圖形軟體光柵化器。目前在做紋理貼圖的時候遇到了麻煩,關於透視校正有幾個不太明白的地方:
1. 透視校正發生在哪一個階段,是在攝影變換與透視變換之間,還是在視口變換之後進行插值之前?2. 透視校正的具體做法是什麼?是包括 z 點在內的坐標點,紋理坐標,顏色,法線等等都在插值前除以 z,插值後再乘以 z 嗎?3. w 的存在作用僅僅只是為了齊次坐標嗎?為何一些說法是除以 w 而不是 z,我只能找到的兩者之間的關係是 w 值就是攝影空間中的 z 值。
透視紋理繪製發生在最後階段,坐標已經完成projection,剔除,裁剪了,然後頂點/w,開始批量繪製掃描線之前,這時候開始計算紋理的位置。使用w還是用z,關係不大,早年的3d引擎,直接/z的,只是後面標準化了以後,發現w更好用,可以同時表示透視投影和正交投影。同時頂點經過標準的mvp矩陣運算後,w和z是承線性關係的,方便對z/w做 [0,1] 的cvv裁剪。你可以理解成w就是另外一個z。以前屏幕坐標:
x" = x / z * d + A
y" = y / z * d + A
現在是
x" = x / w * d + A
y" = y / w * d + A
x3" = x1" + (x2" - x1") * t
(1 / w3) = (1 / w1) + ((1 / w2) - (1 / w1)) * t
x3" = x1" + (x2" - x1") * t
(u3 / w3) = (u1 / w1) + ((u2 / w2) - (u1 / w1)) * t
(v3 / w3) = (v1 / w1) + ((v2 / w2) - (v1 / w1)) * t
具體到代碼裡面的做法就是三角形的三個頂點/w以後,u和v也同時/w,然後把w換成自己的倒數:w = 1 / w,及把頂點數據:
(x, y, z, w) + (u, v)
變換成:
(x / w, y / w, z / w, 1 / w) + (u / w, v / w)
然後用 1/w, u/w, v/w進行屏幕空間插值,具體繪製某個點的時候,先從1/w求倒得到w,然後乘以 u/w, v/w得到 u, v,就可以了。
更進一步,可以證明,所有在三維空間里同x,y,z成線性關係的變數,不管是紋理坐標,頂點色或者法向還是其他,他們在屏幕空間里的插值規則都可以通過:插值前先/w,插值後要用時再 * w得到具體值,然後我們把這類三維空間里同x,y,z成線性關係的變數統進行統一的批量處理,和OpenGL的 attribute,varying處理方法相同。
--
1、透視校正可以在triangle setup時插值三角形內部uv的時候做。2、透視校正不是先除以在乘以,透視校正的原因是要求插值的時候相同空間的量插值相同空間的量,不要使用perspective space的量去插值view space的量。主要是uv:直觀的說,如果不使用1/z插值投影的話,紋理會是這樣的 :
推薦閱讀:
※有哪些辦法繪製分形?
※工作6年的程序員,還在原地踏步怎麼辦?
※透視裁剪到底發生在哪個階段?
※海島奇兵中海邊的浪花是如何實現的,使用shader還是序列幀動畫?