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

歡迎訪問(wèn) 生活随笔!

生活随笔

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

编程问答

反走样和OpenGL多重采样

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH |GLUT_RGBA | GLUT_MULTISAMPLE);

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

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

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

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

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

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

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

A B C D ————> 4個(gè)采樣掩碼位

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

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

然后再計(jì)算平均值的時(shí)候考慮到某一個(gè)掩碼是0,那么該子采樣點(diǎn)的顏色就不參與最后的運(yùn)算了。

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

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

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

void glSampleCoverage( GLclampf value,GLboolean invert);

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

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

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

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

以上是所有OpenGL中和MSAA反走樣相關(guān)的內(nèi)容。反走樣是一個(gè)十分龐大的主題,讀者也可以通過(guò)FBO自己實(shí)現(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)載請(qǐng)附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/csxiaoshui/article/details/78932603

總結(jié)

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

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