2021年11月28日 星期日

為什麼要在4D space裁切三角形

原本我覺得要在camera space作裁切
(用視錐的6個平面)

可再想想
我們使用數學庫生成projection Matrix時
zFar和zNear(in camera space)
其實是被編碼在Matrix的2個component上面的。


而傳給Verext Shader 的,可以有下面2種情況

第1種:MVP分開

第2種:MVP乘在一起

第1種情況
如果OpenGL知道你傳的是那一種Projection Matrix
可以用Projection的2個component
重新解出zNear和zFar(但這也是Camera Space的)
但OpenGL其實不知道你傳那一種

第2種情況
我猜不行

由上可知
它不需要知道zNear和zFar

projection space ( or clip space)

乘上projection Matrix之後,視椎體的fov變成了一定是90度角
(原來在camera space 時不一定是90度,但除tanHalfFov項之後就一定是90度了)
這樣一來裁切平面就變成有4個是固定的
(和y軸夾45度角的2個平面,和x軸夾45度角的2個平面)

備註:
線段和這4個平面的交點
平面方程式是 dot( (P-C),N )= 0
和y軸夾45度角的2個平面,其中1個是
N=(1,0,-1),C=(0,0,0)所以該平面是 x=z

三角形 Vo、V1、V2
其中的一邊所在的射線為
Vo+t(V1-Vo)

代入 x=z 平面
解出t就能算出交點了
 

能不能6個平面都在NDC裡作裁切?

4個平面不能在NDC裡裁切,原因是:
如果A點和B點構成線段L
而L和其中一個裁切平面的交點為S
在projection space空間裡,A、B、S三點共線
但在NDC space,這3點不能保證共線
(這一段是在OpenGPU論壇看到的,我只是把前人說的話,畫成圖)

✖️是和y軸夾45度角的2個平面
(x , y , z , w)是Projection space的點
(1)畫的是(x , y , w)
(2)畫的是(x/w , y/w , 1)
(3)畫的是(x/w , y/w , z/w)

這張圖的NDC z是位在0~1之間
你會發現B的位置跑掉了

projection space ( or clip space)

仔細看clipping裡的條件
它說6個平面都可以在
projection space判定是否需要clip
為什麼?

以Directx為例

model view projection 全部使用左手座標
view space的頂點為Vv =(x, y, zv)
projection space的頂點為Vp = (x, y, zp , wp)
z= a zv + b
w= zv
NDC space z= z/ wp

當Vp在近平面和遠平面之間
zn會落在0和1之間
0 ≤ zn ≤ 1
0 ≤ z/ wp ≤ 1
0 ≤ zp ≤ w式A

當Vp在遠平面外面
zn > 1 
z/ wp > 1 
zp > wp 

當Vp在近平面外面
zn < 0
z/ wp < 0
zp < wp

所以用式A就可以判定是否需要clip
完全不需要知道近遠平面是什麼!
(OpenGL也是類似的道理)

當三角形的2個頂點V0和V1需要被裁切
對線段做插值就可以得出裁切平面(遠平面)上的點
(視錐的其他5個平面也可以套用類似的方法)

NDC之後還有1次z的remapping

 
參考資料

寫完軟光柵後


圖 Screen Space
先解出t,s找到點hit,就能算出α

發現其實不必在Clip space裁切左、右、上、下
因為在Screen Space 光柵化三角形前
會找出包圍三角形的矩形
而這個矩形又會受限於Screen Space的大小
效果等於在Clip space裁切左、右、上、下

但是不裁切的話
矩形超出Screen外面的部分
也會在loop裡
雖然沒做任何事

實作中發現的有趣效果


沒有留言:

張貼留言