日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

反走样和OpenGL多重采样

發(fā)布時間:2023/12/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 反走样和OpenGL多重采样 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1. 反走樣
在計算機圖形學(xué)中,在屏幕上顯示對象時,可能會出現(xiàn)許多的“鋸齒”,這些鋸齒是由頂點數(shù)據(jù)像素化之后成為片段的方式所引起的,由于將數(shù)學(xué)意義上的坐標(biāo)轉(zhuǎn)換到物理的顯示器硬件上進(jìn)行顯示,顯示器是有一個個像素點構(gòu)成的,并不能實現(xiàn)數(shù)學(xué)意義上的“無限小”的描述。關(guān)于產(chǎn)生鋸齒的更詳細(xì)的介紹可以參考OpenGL學(xué)習(xí)腳印: 反走樣初步(Anti-aliasing basic)

為了消除“鋸齒”,圖形工作者提出了許多抗鋸齒的算法(也稱為反走樣[Anti-aliasing]算法),本文主要介紹OpenGL中提到的一種反走樣方法——多重采樣(Multisample antialiasing簡稱 MSAA)。接觸到這一主題時,查閱了很多資料,發(fā)現(xiàn)網(wǎng)絡(luò)上許多內(nèi)容都大同小異,很多內(nèi)容并沒有參考價值。整體的思路說清楚了,但是一旦涉及到某一項技術(shù),最難的往往是技術(shù)中的細(xì)節(jié)部分。本文記錄我個人在理解MSAA時候比較困惑的點,在理解之后記錄下來。

2. Supersampling
在理解MSAA之前,有必要先理解一下什么是SuperSampling (字面翻譯是超采樣,簡稱是SSAA),超采樣就是加大采樣的點,提供比屏幕分辨率更多的采樣點。是渲染的時候按照顯示器分辨率的若干倍來渲染,例如顯示器1024x768,那么SSAA 4X就是4096x3072。
?

上圖是OpenGL決定一個像素顏色采用的算法,如果紅色的采樣點(像素中心位置)落在三角形區(qū)域,那么這個像素就被認(rèn)為屬于三角形,從而會著色成為三角形的顏色。但是邊緣部分的像素并沒有“完全屬于”三角形,那么這些像素的顏色應(yīng)該是某種介于邊緣多種顏色的“過渡色”比較合理一點。
SSAA的想法比較簡單,就是擴(kuò)大采樣點,生成一些次像素級別的采樣點(sub-pixel)。有點類似股份公司的感覺,把像素理解成為一家公司,那么這家公司歸屬誰呢?在中心區(qū)域,由于完全被三角形區(qū)域所包含,那么屬于三角形沒有什么爭議,但是邊緣部分的像素由于并沒有完全被三角形占據(jù),那么它的所有權(quán)問題就應(yīng)該是多個股東決議的結(jié)果,根據(jù)大家股份占用的大小來中和最后的結(jié)果。

在像素中如何添加新的次像素級別的采樣點,方法很多。不同的采樣點設(shè)計方式最終對場景渲染的結(jié)果也不同。以下是一些采樣點的選擇方式:

得到次級像素的采樣點之后,把這個場景渲染到一個更高分辨率的緩沖區(qū)A中,然后再從A緩沖區(qū)中采樣出和屏幕分辨率一樣的像素,像素的顏色使用A緩沖區(qū)中的像素顏色插值得到。整體的思路如下圖所示:

上圖中使用4個采樣點,如果不使用SSAA技術(shù),那么最終屏幕上這個像素的顏色是中心位置的黃色,使用了SSAA之后,這個像素的顏色是淡淡的棕黃色,這個顏色綜合了像素中其他的顏色值計算而來的。(圖示中使用的是簡單的求平均值的方法,在實際中可能會有其他的算法來計算,但是整體思路還是一樣的)

在SSAA方法中,有一個需要注意的地方是:所有的次級采樣點和未使用SSAA中采樣點的地位是一樣的,假設(shè)有片元shader需要在每一個像素上運行,那么SSAA中片元shader也會在每一個次級像素上運行。理解這一點非常的關(guān)鍵,它是SSAA和MSAA最重要的一個區(qū)別。

SSAA的缺點:通過上面的分析可以知道SSAA需要占用更大的顯存空間,它需要更大緩沖區(qū),采用4x、8x、16x那么使用的空間是未開啟SSAA的4倍,8倍和16倍。另外SSAA需要每一個shader在所有次級片元上都同樣的運行一遍,這也是一筆可觀的計算開銷,會顯著地降低FPS。

3. MSAA
有了SSAA的基礎(chǔ),那么理解多重采樣(MSAA)就簡單很多了。MSAA中增加采樣的方式和SSAA是一樣的,MSAA同樣也需要一個分辨率更高的緩沖區(qū)(假設(shè)命名是Anti-Buffer),但是MSAA并不是像SSAA一樣把次級采樣點當(dāng)成類似未開啟反走樣中采樣點同等地位來對待,它采用另一種方式。
示意圖如下:

圖示中兩個三角形的圖元都包含了像素的采樣點(圓形位置),4個叉代表著該像素的4個子采樣點。在開啟MSAA之后的過程如下:
首先由于屏幕背景清空色是白色,那么Anti-Buffer中的每一個子采樣點的顏色都設(shè)置成了白色,
假設(shè)藍(lán)色的三角形首先繪制,由于它包含像素的采樣點,因此在跑了一次shader之后,左下角的這個2個子采樣點在Anti-Buffer緩沖區(qū)的值被藍(lán)色填充,然后開始繪制黃色三角形,由于它也包含像素的采樣點,因此也會跑一次shader,假設(shè)計算的結(jié)果是黃色。由于右邊的采樣點被它包含,因此被設(shè)置成黃色,最終這個像素對應(yīng)在Anti-Buffer緩沖區(qū)中4個子采樣點的顏色是白色、黃色、藍(lán)色、藍(lán)色。最終的顏色由這4個顏色計算平均得到。

也就是說:MSAA每一個像素上shader只運行一次,運行的結(jié)果會復(fù)制到每一個包含了子采樣點的緩沖區(qū)中。而不是像SSAA那樣每一個子采樣點都運行一次shader。大大減少了shader的運行次數(shù)。

4. MSAA在OpenGL中的使用
網(wǎng)絡(luò)上許多關(guān)于MSAA在OpenGL中的使用方式都沒有說的很清楚,這里就介紹一下OpenGL中的MSAA。

OpenGL中有很多狀態(tài)變量,默認(rèn)情況下基本都是關(guān)閉的(比如光照計算、混合計算、深度測試等等),但是只有兩個狀態(tài)默認(rèn)是開啟的,MSAA就是其中之一(另一個是Dither),要使用OpenGL提供的MSAA,需要申請一個可以進(jìn)行超采樣的緩沖區(qū)(也就是我們上文說的Anti-Buffer),申請的方式和窗口系統(tǒng)有關(guān),在GLUT中申請的方式很簡單,只需要添加一個枚舉值的變量GLUT_MULTISAMPLE即可:

glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH |GLUT_RGBA | GLUT_MULTISAMPLE);

添加緩沖區(qū)之后,開啟多重采樣即可(默認(rèn)是開啟的可以不用顯式設(shè)置),開啟方式:glEnable(GL_MULTISAMPLE);

使用方式就是這么簡單,另外在OpenGL中還有一些多重采樣控制的參數(shù)需要設(shè)置,相關(guān)的API如下:

開啟多重采樣覆蓋率的設(shè)置
在MSAA介紹部分,我們列舉的例子中,說到了最后的顏色由白色、黃色、藍(lán)色、藍(lán)色。這4個顏色計算平均得到。這里的描述是不完全準(zhǔn)確,OpenGL默認(rèn)情況下是會直接取4個顏色的平均值,但是也可以添加更多的控制。

默認(rèn)計算算法((color1+color2+color3+...+colorn) / n),需要注意這時候color的alpha值是不參與計算的。

如果進(jìn)行下面的設(shè)置,那么計算算法會改變,

4.1. glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
設(shè)置之后alpha值參與計算

由于多重采樣的實現(xiàn)方式很多,OpenGL也沒有規(guī)定硬件應(yīng)該怎么實現(xiàn)多重采樣,都是交給硬件自身處理。因此這里我們描述一種可能的多重采樣的處理過程:
當(dāng)我們使用4x,8x等MSAA時,OpenGL會為每一個像素分配一個掩碼值,這個掩碼值的位數(shù)是由子采樣的點數(shù)決定的,也就是說4x是分配4位,8x是分配8位。分配完成之后,這些位記錄了一個子采樣點是否被其他幾何圖元覆蓋到了,以3中的情況為例,由于那4個采樣點有3個被覆蓋到了,因此那個像素中的Coverage掩碼是 0 1 1 1

A B C D ————> 4個采樣掩碼位

0 1 1 1 ————–>覆蓋掩碼值

白色 藍(lán)色 藍(lán)色 黃色 ——>MSAA采樣緩沖區(qū)值

然后再計算平均值的時候考慮到某一個掩碼是0,那么該子采樣點的顏色就不參與最后的運算了。

上面說的是正常的處理過程,一旦我們設(shè)置了glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE),那么這個掩碼就要開始運算了:設(shè)置之后,OpenGL會根據(jù)MSAA緩沖區(qū)中顏色值的Alpha成分,生成一個掩碼值,并與這個原來的掩碼進(jìn)行按位與的運算。(alpha值是一個浮點數(shù)的值,怎么進(jìn)行按位與的運算呢?原來OpenGL可以通過映射,將某一范圍內(nèi)的值映射成一個整數(shù)),生成一個新的掩碼值。具體來說是:
一個fragment的Alpha值在0~1間,它對應(yīng)著一個值。還是以4XMSAA為例,這個值也是xxxx的形式,Alpha為0對應(yīng)了0000,alpha為1對應(yīng)了1111,至于中間的值的對應(yīng)關(guān)系,OpenGL是交由顯卡制造商決定的——其實一般就是類似[0~0.249 -> 0000, 0.25~0.499 -> 0001, 0.5~0.749 -> 0011, 0.75~0.99-> 0111]這樣(在D3D11中,就可以自定義這個值)。這個值與與coverage mask作一次邏輯按位與操作獲得新的coverage mask。

4.2 glEnable(GL_SAMPLE_ALPHA_TO_ONE);
設(shè)置多重采樣中每一個子采樣點的顏色alpha成分是1。

4.3 . glSampleCoverage
開啟自定義設(shè)置,需要2個函數(shù)調(diào)用
glEnable(GL_SAMPLE_COVERAGE)
glSampleCoverage
這里面glSampleCoverage的函數(shù)原型如下:

void glSampleCoverage( GLclampf value,GLboolean invert);

第一個參數(shù)是 value,表示掩碼值
第二個參數(shù)是 invert,表示是否翻轉(zhuǎn)計算

第一次看到這個接口API時,發(fā)現(xiàn)是一個float的value值,OpenGL的spec文檔中一直提到要做按位的與運算,我就一臉懵逼了,按位運算不是整型才有的運算操作嗎?是不是說這個value會被cast成一個整型,既然要cast成一個整型為什么不設(shè)置參數(shù)類型就是整型呢?

事實上是這樣的:這個浮點數(shù)的值會被映射成一個整型數(shù),和之前alpha_to_coverage類似

glSampleCoverage的效果和 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);有點類似,都是設(shè)置掩碼和原來像素的coverage掩碼作按位與的運算,不同之處是后者使用顏色成分的alpha值運算。而這個函數(shù)是自己指定一個值,這個值是value映射后的整型值。第二個參數(shù)invert是對這個value映射后的整型值作按位取反操作。然后再與像素的coverage掩碼作運算。

以上是所有OpenGL中和MSAA反走樣相關(guān)的內(nèi)容。反走樣是一個十分龐大的主題,讀者也可以通過FBO自己實現(xiàn)反走樣的算法,關(guān)于在FBO中作反走樣,可以閱讀參考資料中的內(nèi)容。

5. 參考資料
1. OpenGL學(xué)習(xí)腳印: 反走樣初步(Anti-aliasing basic)
2. 抗鋸齒
3. Supersampling
4. Multisample Anti-Aliasing
5. Rasterization Rules
6. 亂彈紀(jì)錄II:Alpha To Coverage
————————————————
版權(quán)聲明:本文為CSDN博主「csxiaoshui」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/csxiaoshui/article/details/78932603

總結(jié)

以上是生活随笔為你收集整理的反走样和OpenGL多重采样的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。