Computer Graphics note(3):視圖變換 & 光柵化

一.前提

Games101 Lecture5-6-7
在M(模型)V(視圖)P(投影)變換之後,得到[1,1]3[-1,1]^3,接下來就是將其映射到屏幕空間上去。
M變換:https://blog.csdn.net/Enterprise_/article/details/106880754
VP變換:https://blog.csdn.net/Enterprise_/article/details/106934622

二.屏幕

在圖形學中,屏幕被認爲是一個二維數組,其元素是pixelpixel(像素),數組的大小叫做resolutionresolution(分辨率),同時屏幕也是一種典型的光柵化圖形設備光柵化(Rasterization):把三維空間的幾何形體顯示在屏幕(光柵化設備)上

三.屏幕空間(Screen Space)

屏幕空間相當於在屏幕(高爲heightheight,寬爲widthwidth)上建立一個座標系,其原點在屏幕的左下角,如下圖所示:

在這裏插入圖片描述

前提規定:像素的座標(x,y)(x,y)是整數值,並且(x,y)[width1,height1](x,y)\in[width-1,height-1],像素中心在(x+0.5,y+0.5)(x+0.5,y+0.5),屏幕空間覆蓋範圍爲(0,0)>(width,height)(0,0)->(width,height)

四.視口變換(映射([1,1]3([-1,1]^3)

想要將該立方體映射到屏幕上,需要暫時忽略其ZZ座標(ZZ不變),這樣就變成了[1,1]2[-1,1]^2,將其縮放(對x,yx,y進行縮放)到[0,width][0,width]X[0,height][0,height]。並且由於原來的立方體中心在原點,現在需要將其平移到屏幕空間的中心(width2,height2)(\frac{width}{2},\frac{height}{2})上。此處的變換被稱爲視口變換(Viewprot transform),其變換矩陣MviewportM_{viewport}如下所示:
Mviewport=[width200width20height20height200100001] M_{viewport}=\begin{bmatrix} \frac{width}{2} &0&0&\frac{width}{2}\\ 0&\frac{height}{2} &0 &\frac{height}{2}\\ 0&0&1&0 \\ 0&0&0&1 \end{bmatrix}

五.光柵化

至此,經過了MVP和視口變換之後,三維空間的幾何形體就被映射到了屏幕空間裏,想要得到圖像,需要用這些信息進行光柵化,將其變成像素。
光柵化過程中繪製的基本圖元是三角形,因爲其內外定義良好,是最基礎的多邊形。

1.傅里葉變換

這裏需要知道關於頻域(Frequency Domain)的東西來輔助理解,我們需要用到傅里葉分析,也就是傅里葉級數(Fourier Serie)和傅里葉變換(Fourier Transformation)。兩者關係如下圖:

在這裏插入圖片描述

簡單來說,傅里葉級數是個時域裏週期連續,頻域裏非週期離散的函數;而傅里葉變換是將時域(spatial domain)裏非週期連續信號轉換爲頻域(frequency domain)裏非週期連續的信號。
舉個例子,對於下面這個式子:

在這裏插入圖片描述

對其作傅里葉變換,然後將不同頻率的段顯示出來,再對其進行同樣的採樣重建,結果如下圖所示:

在這裏插入圖片描述

2.濾波(Filtering)

濾波是把特定頻率的內容去除。下圖左圖爲原圖像,右圖爲傅里葉變換之後的頻譜。定義右邊圖的中心爲低頻區域,往外頻率越高,不同頻率區域所包含的信息通過其亮度來表示圖像的頻率信息可以理解爲圖像相鄰像素間色彩的變化,可見該圖大部分都是低頻信息,少部分高頻信息。分析信號時一般認爲其爲週期重複信號,對於不重複的,如下圖進行連續平鋪,即連續同樣的圖片連載一起,這樣在邊界處就會出現十字線(信號劇烈變換)。

在這裏插入圖片描述

(1)高通濾波

假如把去除低頻信號後,再逆傅里葉變換,就可以看到高頻信息表示圖像內容的邊界(信號劇烈變換)。這樣的濾波稱爲高通濾波(High-pass filter)。如下圖從右到左。

在這裏插入圖片描述

(2)低通濾波

在這裏插入圖片描述

低通濾波(Low-pass filter)只留下低頻信息。高頻代表邊界,去除之後邊界就變得模糊了。

(3)帶通濾波

在這裏插入圖片描述

在這裏插入圖片描述
上面兩圖都是去除高頻和低頻信息,但是中間的頻率確實一個可選範圍,所以當範圍往外擴大的時候,其結果就會偏向高通濾波。

3.卷積(Convolution)

(1)定義(Filtering = Convolution(= Averaging)

**圖形學上簡化的卷積操作(簡化定義,非數學定義),是將濾波器(卷積核)在信號上進行移動,兩者重複位置進行點乘,結果寫回其中心(新的信號)。**如下圖所示。

在這裏插入圖片描述

(2)Convolution Theorem(卷積定理)

時域(spatial domian)裏兩個信號的卷積等於兩個信號頻域的乘積,反過來,時域上的乘積等於頻域上的卷積。

也就是說,以下兩者等價(時域卷積=頻域乘積),例子如下圖:

  1. 對一幅圖可以先通過濾波器在時域上進行卷積
  2. 可以先把這幅圖先通過傅里葉變換變到頻域上,再把濾波器(卷積核)也變換到頻域上,兩者相乘後逆傅里葉變換到時域上

在這裏插入圖片描述

其中所用的濾波器(卷積核)(如下圖)有歸一化操作((乘以19\frac{1}{9})),因爲需要保證變換前後的圖像亮度不變。這樣的濾波器爲低通濾波器,其當大小越大時結果越模糊。

在這裏插入圖片描述

4.光柵化基本方式–採樣(Sampling)

(1)例子(輔助理解)

此處的採樣是指用像素的中心來對屏幕空間進行採樣。
比如將像素中心套用到判斷函數上,得到每個像素中心在屏幕空間上的對應值(用於判斷是否在三角形內),假設函數如下:
insidde(triangle,x,y)={1,in0,notin insidde(triangle,x,y)=\begin{cases} 1,in \\0, not&in \end{cases}
然後對屏幕上像素判斷,如下圖示例:

在這裏插入圖片描述

對於insideinside函數可以用叉積的正負號來進行判斷,三邊按順序與點進行判斷,符號不變則點在三角形內,反之不在。對於點在邊界上的情況,自行決定。

對於像素檢查不需要檢查的所有像素,只需要檢查包圍盒(BoundingBox)(Bounding Box)裏的像素即可,包圍盒範圍可由三角形頂點信息得到,如下圖所示:

在這裏插入圖片描述

假設每個像素是個顏色均勻的小方塊(暫時定義),那麼光柵化之後如下圖所示,有明顯的走樣(Aliase)現象(鋸齒):

在這裏插入圖片描述

(2)Sampling = Repeating Frequcncy Contents

採樣實際就是在重複頻率(頻域)上的內容。如下圖(來源:https://www.researchgate.net/figure/The-evolution-of-sampling-theorem-a-The-time-domain-of-the-band-limited-signal-and-b_fig5_301556095)

在這裏插入圖片描述
假設其中aa爲原函數(時域信號),bb爲其經過傅里葉變換後在頻域上的結果。如果要對aa進行採樣(得到原信號上離散的點)的話,則用另一個函數(衝激函數)cc乘以aa得到離散的值(如ee所示,即採樣結果)。此時考慮卷積定理,時域乘積=頻域卷積,即acac在時域上的乘積等於bdbd(acac在頻域上的結果)在頻域上的卷積。所以從結果上看,採樣就是在重複原始信號的頻譜

5.Aliase(走樣)

採樣會產生Artifacts(瑕疵),比如鋸齒(在空間中採樣),摩爾紋(Moiré Patterns)(在空間中採樣),Wagon Wheel Illusion(對時間採樣,人眼對時間的採樣低於運動的速度)。

(1)產生原因 & 定義

Aliasing Artifacts產生的本質原因是信號(函數)變換過快(高頻率),但是採樣速度跟不上。從上可以知道高頻率必須用更快的採樣方法,否則重建效果是非常差的。所以走樣爲對兩個頻率截然不同的信號當採用同樣的採樣方法,否則得到的結果卻無法區分。

在頻譜上表現爲原信號和搬移信號發生混疊現象。如下圖所示,當採樣率越低時(時域上採樣點之間的間隔越大),在頻譜上就表現爲信號之間的間隔就越小,發生混疊現象即爲走樣。

在這裏插入圖片描述

(2)反走樣

從走樣的原因出發,理論上只要提高採樣率,就能解決走樣的問題,但是受物理限制(比如高分辨率顯示器)。

反走樣的方法:Blurring(Pre-Filtering)Before Sampling,也就是在採樣之前先對三角形濾波(模糊),注意其邊界像素取中間值,如下圖所示:

在這裏插入圖片描述

例子如下:

在這裏插入圖片描述

值得一提的是如果先採樣再模糊的話也是走樣,不是反走樣,如下圖:

在這裏插入圖片描述

這裏的反走樣實際就是使用了低通濾波,也就是說對一個信號去除高頻信息後再採樣。用上面講採樣時的採用例子,在頻譜上表現如下:

在這裏插入圖片描述

上面說過,走樣是原信號和搬移信號發生混疊現象,而低通濾波(上圖中的虛線矩形)去除高頻信號後再採樣後,就沒有混疊了,即反走樣。

6.三角形反走樣操作

至此,想要對三角形反走樣,就要先對三角形覆蓋的像素區域進行模糊操作,這裏只需要使用卷積(平均)操作。但是實際操作並不適用,因爲覆蓋區域不好計算。使用其他方法來模擬,比如MSAA(Multi-Sampling Anti-Aliasing),需要明確的是MSAA模擬的是反走樣的第一步,即模糊(濾波)的過程

(1)MSAA(Multi-Sampling AA)(光柵化階段)(通過Supersampling來計算三角形的覆蓋率)

在這裏插入圖片描述
Supersampling,首先將一個像素劃分(劃分方法多樣,上圖中的網格劃分只是一種劃分方法)稱爲更多個更小的"像素",並認爲每個小的"像素"(次像素,採樣點)有其中心,再判斷其是否在三角形內,然後對結果進行平均。這樣就三角形對原像素覆蓋區域的近似,很明顯,劃分越多結果越準確。從這裏會發現MSAA導致計算量倍增,其大小和劃分結果有關,但是實際工作中會因爲劃分結果的不同以及相鄰像素對次像素的複用使得計算量不會增加太多。

舉個例子,如下圖,先劃分每個像素爲2x2:

在這裏插入圖片描述

然後對每個像素進行判斷,比如左上角第一個像素,四個小"像素"都沒有被三角形覆蓋,則認爲原像素不在三角形內;而三角形上部的一個像素,有3個小"像素"被覆蓋,1個沒有,覆蓋率爲75%75\%,則認爲原像素在三角形內,如下:

在這裏插入圖片描述

全部都判斷完之後,結果如下:

在這裏插入圖片描述

其最後結果如下,每個像素變成了顏色平均的,數值爲覆蓋率。至此走樣的第一步(模糊操作)就完成了,MSAA只針對第一步。之後再進行採樣即可。

在這裏插入圖片描述

(2)其他方案FXAA& TAA& Super resolution/super sampling

FXAA(Fast Approximate AA) 和採樣無關,屬於圖像的後期處理技術,對於有鋸齒的圖像,通過圖像匹配找到鋸齒部分,然後替換成沒有鋸齒的圖像。

TAA(Temporal AA) 的思想是複用上一幀像素的結果,對於靜止圖像而言,相當於把MSAA對應的Sample分佈到時間軸上,並且對於當前這一幀而言不引入其他操作。

Super resolution(超分辨率)/Super Sample(超採樣),將低分辨率圖像"恢復"成高分辨圖像,這個和抗鋸齒本質是一樣的,解決的是Sample不足的問題。方法有DLSS(Deep Learning Super Sampling),將缺失的像素"猜測"出來。

7.深度測試算法(Z-Buffer,像素內)

當有多個不同的三角形,距離相機位置,三角形之間存在遮擋問題。解決方法有Painter’s Algorithm,即繪畫順序從後往前,這樣就能解決遮擋問題,應用到光柵化上,也就是先處理距離觀測點遠的對象,但是深度(距離觀測點的距離)難以定義。比如下圖存在互相遮擋:

在這裏插入圖片描述

這就需要Z-Buffer算法來解決,其思想是當考慮到對於三角形的相對深度不好排序時,轉而對像素進行排序,在每個像素內記錄該像素所表示的幾何物體的最淺的深度(距離觀測點最近的距離)。當和MSAA結合時,就應該對每個採樣點進行Z-Buffer。

在具體實現的時候,同步生成成品圖像信息和深度圖(深度緩存),深度圖只存每個像素所表示的幾何物體的最淺的深度信息。前者存儲在frameframe bufferbuffer(存顏色值)中,後者存儲在depthdepth bufferbuffer(存深度信息)中。

在之前的視圖變換中提到過,相機(觀測點)是看向Z-Z方向的,所以物體越遠其ZZ值越小(負數)。但是考慮深度測試,爲了方便,認爲此時的ZZ值是距離相機的距離(正數),距離近深度淺(深度越小,替換成顏色值,也就越黑),反之深度大。

Z-Buffer示例圖如下:

在這裏插入圖片描述

(1)Z-Buffer僞碼

Initialize depth buffer to ∞
During rasterization:
	for (each triangle T)
		for (each sample (x,y,z) in T)
			if (z < zbuffer[x,y]) // closest sample so far
				framebuffer[x,y] = rgb; // update color
				zbuffer[x,y] = z; // update depth
			else
				; // do nothing, this sample is occluded

Z-Buffer複雜度是O(n)O(n),因爲這裏沒有對三角形進行排序(與順序無關),只是求每個像素看到的最小深度值。

Z-Buffer算法僞碼如上,首先是初始化,接着在光柵化階段,對每個三角形(與順序無關)進行光柵化,得到三角形覆蓋的每一個像素。比較每個像素當前所記錄的深度zbuffer[x,y]zbuffer[x,y]和新三角形對應的深度zz,如果當前的深度更大,說明距離更遠,新三角形會將其覆蓋,則進行更新,反之則什麼也不做。例子如下,兩個三角形互相遮擋,(可以想象紫色的三角形是個傾斜(遠離相機方向)的三角形):

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章