顯示具有 Rasterization 標籤的文章。 顯示所有文章
顯示具有 Rasterization 標籤的文章。 顯示所有文章

2023年3月30日 星期四

DX、OpenGL、Vulkan在那做Face cullng?

 

開場

設定逆時鐘方向是三角形的正面


這是我們的三角形和camera設定

使用glm::lookAt,預設是右手的Camera

為什麼3角形沒有出來?

結果1
程式碼來自vulkan tutorial

但是他的可以

結果2
程式碼來自vulkan tutorial

然後改成這樣也行?

結果3


to NDC space


肉眼可見DirectX、openGL、Vulkan
大家在NDC三角形都是逆時針

如果vulkan是在這裡做face culling
結果1就會看到三角形

結果1並沒看到
所以不是在這裡做!

viewport space

變換到viewport space


判定順時鐘、逆時鐘的座標系必須是
x軸從銀幕左往右
y軸從銀幕下往上

所以我們先自己鏡射一下
如果是在這裡做face culling
Vulkan是逆時鐘
結果1就會看到三角形

結果1並沒看到
所以也不是在這裡做!

那麼現在

假設存在1個 Face cullng space

用來判定face culling

這樣一來
DirectX和OpenGL都是逆時鐘,看得到三角形
而Vulkan是順時鐘,看不到
結果1相符

結果2

代表在camera space先沿著y軸方向鏡射

再乘上projection matrix
Vulkan是順時針
所以不是在NDC做

Vulkan在Screen Spcae是順時鐘
Vulkan在face culling space是逆時鐘

所以結果2看的到

這是一個負負得正的結果

結果3

客製化Projeciton Matrix

去fit這種奇怪的NDC



在Screen Space是順時鐘
在face culling space是逆時鐘

所以結果3看的到

參考資料


Sascha的方法

我們使用右手的Camera

 

直接修改viewport

相當於下面的紅色區塊

在Face culling space是逆時鐘方向

所以能正常顯示

不需要變換到Face culling space

仔細看完VkFrontFace Manual Page
發現它使用的是矩阵求三角形面积的結果再*(-1) 

VkFrontFace Manual Page

因為
viewport space和Face culling space判定的結果就是差1個負號

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裡
雖然沒做任何事

實作中發現的有趣效果


2021年11月27日 星期六

透視校正

假設三角形的3個頂點
在modle space是Am、Bm、Cm

頂點乘上Model View Projection Matrix(MVP)後
變換到Projection space
MVP(Am) = A、MVP(Bm) = B、MVP(Cm) = C
A(x)代表存取頂點A的屬性x,以推類推
B(w)代表存取頂點B的屬性w

找出P(w)

透視校正就是
透過P(w)反推出「在黃色三角形上內插的結果」

2019年11月12日 星期二

仿射變換

為什麼?
先內插三角形頂點、再做座標變換=先做座標變換、再內插三角形頂點

線性變換1 link
線性變換2 link
仿射變換1 link

所以可以先在shader裡對三角形的3個頂點做變換 vMVP=v' 後 (clip space)
再內插三角形 (補充1)

v是頂點
MVP =Modle ✖️ View ✖️ Projection Matrix


補充1:
其實是在screen space做三角形內插
但「screen space三角形的內插權重」會等於「NDC三角形的內插權重」α、β、γ
有了α、β、γ,再用透視校正,得到clip space的三角形內插權重α'、β'、γ'