原本我覺得要在camera space作裁切
(用視錐的6個平面)
可再想想
我們使用數學庫生成projection Matrix時
zFar和zNear(in camera space)
其實是被編碼在Matrix的2個component上面的。
第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 =(xv ,
yv , zv)
projection space的頂點為Vp = (xp ,
yp , zp , wp)
zp = a zv + b
wp = zv
NDC space zn = zp / wp
當Vp在近平面和遠平面之間
zn會落在0和1之間
0 ≤ zn ≤ 1
0 ≤ zp / wp ≤ 1
0 ≤ zp ≤ wp 式A
當Vp在遠平面外面
zn > 1
zp / wp > 1
zp > wp
當Vp在近平面外面
zn < 0
zp / wp < 0
zp < wp
所以用式A就可以判定是否需要clip
完全不需要知道近遠平面是什麼!
(OpenGL也是類似的道理)
當三角形的2個頂點V0和V1需要被裁切
對線段做插值就可以得出裁切平面(遠平面)上的點
(視錐的其他5個平面也可以套用類似的方法)
|
NDC之後還有1次z的remapping
參考資料
- 虎書某一小節好像有提到
- 雖說只挑了重點看 Scratchapixel 2.0 - clipping
寫完軟光柵後
圖 Screen Space
先解出t,s找到點hit,就能算出α
|
發現其實不必在Clip space裁切左、右、上、下
因為在Screen Space 光柵化三角形前
會找出包圍三角形的矩形
而這個矩形又會受限於Screen Space的大小
效果等於在Clip space裁切左、右、上、下
但是不裁切的話
矩形超出Screen外面的部分
也會在loop裡
雖然沒做任何事
沒有留言:
張貼留言