版本記錄
版本號(hào) | 時(shí)間 |
---|---|
V1.0 | 2017.09.29 |
前言
OpenGL ES是一個(gè)強(qiáng)大的圖形庫(kù)蝗锥,是跨平臺(tái)的圖形API冲茸,屬于OpenGL的一個(gè)簡(jiǎn)化版本。iOS系統(tǒng)可以利用OpenGL ES將圖像數(shù)據(jù)直接送入到GPU進(jìn)行渲染攘残,這樣避免了從CPU進(jìn)行計(jì)算再送到顯卡渲染帶來(lái)的性能的高消耗确沸,能帶來(lái)來(lái)更好的視頻效果和用戶體驗(yàn)。接下來(lái)幾篇就介紹下iOS 系統(tǒng)的 OpenGL ES框架募闲。感興趣的可以看上面幾篇。
1. OpenGL ES 框架詳細(xì)解析(一) —— 基本概覽
2. OpenGL ES 框架詳細(xì)解析(二) —— 關(guān)于OpenGL ES
3. OpenGL ES 框架詳細(xì)解析(三) —— 構(gòu)建用于iOS的OpenGL ES應(yīng)用程序的清單
4. OpenGL ES 框架詳細(xì)解析(四) —— 配置OpenGL ES的上下文
5. OpenGL ES 框架詳細(xì)解析(五) —— 使用OpenGL ES和GLKit進(jìn)行繪制
繪制到其他渲染目的地
Framebuffer
對(duì)象是渲染命令的目標(biāo)愿待。 當(dāng)您創(chuàng)建一個(gè)framebuffer對(duì)象時(shí)浩螺,您可以對(duì)其存儲(chǔ)的顏色靴患,深度和模板數(shù)據(jù)進(jìn)行精確的控制。 您可以通過(guò)將圖像附加到幀緩沖區(qū)來(lái)提供此存儲(chǔ)空間要出,下圖所示鸳君。 最常見(jiàn)的圖像附件是一個(gè)renderbuffer
對(duì)象。 您還可以將OpenGL ES紋理附加到幀緩沖區(qū)的顏色附加點(diǎn)患蹂,這意味著任何繪圖命令都將呈現(xiàn)到紋理中或颊。 后來(lái),紋理可以作為未來(lái)渲染命令的輸入传于。 您還可以在單個(gè)渲染上下文中創(chuàng)建多個(gè)幀緩沖區(qū)對(duì)象囱挑。 您可以這樣做,以便在多個(gè)幀緩沖區(qū)之間共享相同的渲染管道和OpenGL ES資源沼溜。
所有這些方法都需要手動(dòng)創(chuàng)建framebuffer
和renderbuffer
對(duì)象來(lái)存儲(chǔ)來(lái)自O(shè)penGL ES上下文的渲染結(jié)果平挑,以及編寫(xiě)其他代碼以將其內(nèi)容呈現(xiàn)給屏幕,(如果需要)運(yùn)行動(dòng)畫(huà)循環(huán)系草。
Creating a Framebuffer Object - 創(chuàng)建Framebuffer對(duì)象
根據(jù)您的應(yīng)用程序要執(zhí)行的任務(wù)通熄,您的應(yīng)用程序?qū)⑴渲貌煌膶?duì)象以附加到framebuffer
對(duì)象。 在大多數(shù)情況下找都,配置幀緩沖區(qū)的區(qū)別在于哪個(gè)對(duì)象附加到framebuffer對(duì)象的顏色附加點(diǎn)上:
- 要使用幀緩沖區(qū)進(jìn)行屏幕外圖像處理唇辨,請(qǐng)附加一個(gè)renderbuffer。 請(qǐng)Creating Offscreen Framebuffer Objects能耻。
- 要使用幀緩沖圖像作為后續(xù)渲染步驟的輸入赏枚,請(qǐng)附加紋理。 請(qǐng)參閱Using Framebuffer Objects to Render to a Texture嚎京。
- 要在Core Animation層組合中使用framebuffer嗡贺,請(qǐng)使用特殊的Core Animation感知renderbuffer。 請(qǐng)參閱 Rendering to a Core Animation Layer鞍帝。
1. Creating Offscreen Framebuffer Objects - 創(chuàng)建離屏幀緩沖對(duì)象
用于屏幕外渲染的幀緩沖區(qū)將其所有附件分配為OpenGL ES渲染緩沖區(qū)诫睬。 以下代碼分配帶有顏色和深度附件的幀緩沖區(qū)對(duì)象。
- 創(chuàng)建幀緩沖區(qū)并綁定它帕涌。
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
- 創(chuàng)建一個(gè)顏色
renderbuffer
摄凡,為它分配存儲(chǔ),并將其附加到framebuffer
的顏色附加點(diǎn)蚓曼。
GLuint colorRenderbuffer;
glGenRenderbuffers(1, &colorRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);
- 創(chuàng)建深度或深度/模板renderbuffer亲澡,為其分配存儲(chǔ)空間,并將其附加到framebuffer的深度附件點(diǎn)纫版。
GLuint depthRenderbuffer;
glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
- 測(cè)試幀緩沖區(qū)的完整性床绪。 只有當(dāng)幀緩沖區(qū)的配置更改時(shí),才需要執(zhí)行此測(cè)試。
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) ;
if(status != GL_FRAMEBUFFER_COMPLETE) {
NSLog(@"failed to make complete framebuffer object %x", status);
}
在繪制到屏幕外渲染緩沖區(qū)之后癞己,您可以將其內(nèi)容返回到CPU膀斋,以使用glReadPixels
函數(shù)進(jìn)行進(jìn)一步處理。
2. Using Framebuffer Objects to Render to a Texture - 使用Framebuffer對(duì)象渲染到紋理
創(chuàng)建此幀緩沖區(qū)的代碼與屏幕外的示例幾乎相同痹雅,但是現(xiàn)在將分配紋理并附加到顏色附加點(diǎn)仰担。
- 創(chuàng)建
framebuffer
對(duì)象(使用與 Creating Offscreen Framebuffer Objects相同的過(guò)程)。 - 創(chuàng)建目標(biāo)紋理绩社,并將其附加到framebuffer的顏色附件點(diǎn)摔蓝。
// create the texture
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
- 分配并附加深度緩沖區(qū)(如前所述)。
- 測(cè)試幀緩沖區(qū)的完整性(如前所述)愉耙。
盡管此示例假定您要呈現(xiàn)為顏色紋理贮尉,但其他選項(xiàng)也是可能的。 例如劲阎,使用OES_depth_texture
擴(kuò)展名绘盟,您可以將紋理附加到深度附件點(diǎn),以將場(chǎng)景中的深度信息存儲(chǔ)到紋理中悯仙。 您可以使用此深度信息來(lái)計(jì)算最終渲染場(chǎng)景中的陰影龄毡。
3. Rendering to a Core Animation Layer - 渲染到Core Animation層
核心動(dòng)畫(huà)是iOS上圖形渲染和動(dòng)畫(huà)的核心基礎(chǔ)。 您可以使用主持使用不同iOS子系統(tǒng)(如UIKit锡垄,Quartz 2D和OpenGL ES)呈現(xiàn)的內(nèi)容的圖層合成應(yīng)用程序的用戶界面或其他視覺(jué)顯示沦零。 OpenGL ES通過(guò)CAEAGLLayer
類連接到Core Animation,這是一種特殊類型的Core Animation圖層货岭,其內(nèi)容來(lái)自OpenGL ES renderbuffer
路操。 Core Animation將renderbuffer的內(nèi)容與其他圖層復(fù)合,并在屏幕上顯示生成的圖像千贯。
CAEAGLLayer
通過(guò)提供兩個(gè)關(guān)鍵功能向OpenGL ES提供此支持屯仗。 首先,它為renderbuffer分配共享存儲(chǔ)搔谴。 其次魁袜,它將渲染緩沖區(qū)呈現(xiàn)給Core Animation,用renderbuffer中的數(shù)據(jù)替換了以前的內(nèi)容敦第。 該模型的一個(gè)優(yōu)點(diǎn)是峰弹,只有當(dāng)渲染的圖像更改時(shí),Core Animation圖層的內(nèi)容不需要在每個(gè)幀中繪制芜果。
注意:GLKView
類可以自動(dòng)執(zhí)行以下步驟鞠呈,因此當(dāng)您要在視圖的內(nèi)容層中繪制OpenGL ES時(shí),應(yīng)使用它右钾。
為OpenGL ES渲染使用核心動(dòng)畫(huà)層:
- 創(chuàng)建
CAEAGLLayer
對(duì)象并配置其properties蚁吝。
為獲得最佳性能旱爆,請(qǐng)將圖層的不透明屬性的值設(shè)置為YES。 可以參考Be Aware of Core Animation Compositing Performance灭将。
可選地疼鸟,通過(guò)為CAEAGLLayer對(duì)象的drawableProperties
屬性分配一個(gè)新的值字典來(lái)配置渲染表面的表面屬性。 您可以指定renderbuffer的像素格式庙曙,并指定renderbuffer的內(nèi)容在被發(fā)送到Core Animation之后是否被丟棄。 有關(guān)允許密鑰的列表浩淘,請(qǐng)參閱EAGLDrawable Protocol Reference
捌朴。
- 分配OpenGL ES上下文并使其成為當(dāng)前上下文。 請(qǐng)參閱Configuring OpenGL ES Contexts张抄。
- 創(chuàng)建
framebuffer
對(duì)象(如上面的 Creating Offscreen Framebuffer Objects )砂蔽。 - 創(chuàng)建一個(gè)顏色
renderbuffer
,通過(guò)調(diào)用上下文的renderbufferStorage:fromDrawable:
方法署惯,分配其存儲(chǔ)并傳遞層對(duì)象作為參數(shù)左驾。 寬度,高度和像素格式取自層极谊,用于為renderbuffer分配存儲(chǔ)空間诡右。
GLuint colorRenderbuffer;
glGenRenderbuffers(1, &colorRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
[myContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:myEAGLLayer];
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);
注意:當(dāng)核心動(dòng)畫(huà)層的邊界或?qū)傩愿臅r(shí),應(yīng)用程序應(yīng)重新分配renderbuffer
的存儲(chǔ)空間轻猖。 如果不重新分配renderbuffers帆吻,renderbuffer大小將不匹配圖層的大小咙边;在這種情況下猜煮,Core Animation可以縮放圖像的內(nèi)容以適應(yīng)圖層。
- 檢索顏色renderbuffer的高度和寬度败许。
GLint width;
GLint height;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
在前面的示例中王带,顯式提供了renderbuffers的寬度和高度來(lái)為緩沖區(qū)分配存儲(chǔ)空間。 這里市殷,代碼在分配存儲(chǔ)后從顏色renderbuffer中檢索寬度和高度愕撰。 您的應(yīng)用程序執(zhí)行此操作是因?yàn)轭伾玶enderbuffer的實(shí)際尺寸是基于圖層的邊界和比例因子計(jì)算的。 附加到幀緩沖區(qū)的其他渲染緩沖區(qū)必須具有相同的尺寸被丧。 除了使用高度和寬度來(lái)分配深度緩沖區(qū)之外盟戏,還可以使用它們來(lái)分配OpenGL ES視口,并幫助確定應(yīng)用程序紋理和模型所需的詳細(xì)程度甥桂。 請(qǐng)參閱Supporting High-Resolution Displays柿究。
- 分配并附加深度緩沖區(qū)(如前所述)。
- 測(cè)試幀緩沖區(qū)的完整性(如前所述)黄选。
- 將
CAEAGLLayer
對(duì)象添加到Core Animation
層次結(jié)構(gòu)蝇摸,將其傳遞給可見(jiàn)層的addSublayer:
方法婶肩。
Drawing to a Framebuffer Object - 繪制到幀緩存區(qū)對(duì)象
現(xiàn)在你有一個(gè)framebuffer對(duì)象,你需要填寫(xiě)它貌夕。 本節(jié)介紹渲染新幀并將其呈現(xiàn)給用戶所需的步驟律歼。 渲染到紋理或屏幕外幀緩沖區(qū)的作用類似,僅在應(yīng)用程序使用最終幀時(shí)有所不同啡专。
1. Rendering on Demand or with an Animation Loop - 按需渲染或動(dòng)畫(huà)循環(huán)
當(dāng)渲染到Core Animation圖層時(shí)险毁,您必須選擇何時(shí)繪制OpenGL ES內(nèi)容,就像使用GLKit
視圖和視圖控制器進(jìn)行繪制時(shí)一樣们童。 如果渲染到屏幕外的幀緩沖區(qū)或紋理畔况,每當(dāng)適用于使用這些幀緩沖區(qū)的情況時(shí)進(jìn)行繪制。
對(duì)于按需繪圖慧库,實(shí)現(xiàn)您自己的方法來(lái)繪制和呈現(xiàn)您的renderbuffer跷跪,并在您想要顯示新內(nèi)容時(shí)調(diào)用它。
要使用動(dòng)畫(huà)循環(huán)繪制齐板,請(qǐng)使用CADisplayLin
k對(duì)象吵瞻。 一個(gè)display link
對(duì)象是Core Animation提供的一種定時(shí)器,可讓您將繪圖同步到畫(huà)面的刷新率甘磨。 下面代碼顯示了如何檢索顯示視圖的屏幕橡羞,使用該屏幕創(chuàng)建新的display link
對(duì)象,并將display link
對(duì)象添加到運(yùn)行循環(huán)宽档。
注意:GLKViewController
類可自動(dòng)使用CADisplayLink
對(duì)象來(lái)動(dòng)畫(huà)化GLKView
內(nèi)容尉姨。 僅當(dāng)您需要超出GLKit框架提供的行為時(shí)才直接使用CADisplayLink類。
// Creating and starting a display link
displayLink = [myView.window.screen displayLinkWithTarget:self selector:@selector(drawFrame)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
在drawFrame
方法的實(shí)現(xiàn)之中吗冤,讀取display link
的timestamp
屬性以獲取要渲染的下一個(gè)幀的時(shí)間戳又厉。 它可以使用該值來(lái)計(jì)算下一幀中的對(duì)象的位置。
通常椎瘟,每次屏幕刷新時(shí)觸發(fā)display link
覆致,該值通常為60 Hz,但在不同的設(shè)備上可能會(huì)有所不同肺蔚。 大多數(shù)應(yīng)用程序不需要每秒更新屏幕60次煌妈。 您可以將display link
的frameInterval
屬性設(shè)置為在調(diào)用方法之前執(zhí)行的實(shí)際幀數(shù)。 例如宣羊,如果幀間隔設(shè)置為3璧诵,則您的應(yīng)用程序稱為每第三幀,或大約每秒20幀仇冯。
重要提示:為獲得最佳效果之宿,請(qǐng)選擇app可以連續(xù)的幀率,一種平滑苛坚、一致的幀率產(chǎn)生比不定期變化的幀速率更愉快的用戶體驗(yàn)比被。
2. Rendering a Frame - 渲染一幀
下圖顯示了OpenGL ES應(yīng)用程序在iOS上渲染和展示幀要執(zhí)行的步驟色难,這些步驟包括提高應(yīng)用程序性能的許多提示。
3. Clear Buffers - 清除緩沖
在每幀開(kāi)始時(shí)等缀,擦除所有幀緩沖附件的內(nèi)容枷莉,其中不需要前一幀的內(nèi)容來(lái)繪制下一幀。 調(diào)用glClear
函數(shù)尺迂,將帶有位掩碼的所有緩沖區(qū)進(jìn)行清除笤妙,如下面代碼所示。
// Clear framebuffer attachments
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
對(duì)OpenGL ES使用glClear
“提示”可以丟棄renderbuffer或紋理的現(xiàn)有內(nèi)容噪裕,避免將以前的內(nèi)容加載到內(nèi)存中進(jìn)行的昂貴的操作危喉。
4. Prepare Resources and Execute Drawing Commands - 準(zhǔn)備資源和執(zhí)行繪制命令
這兩個(gè)步驟包括您在設(shè)計(jì)應(yīng)用程序架構(gòu)時(shí)所做的大多數(shù)關(guān)鍵決策。 首先州疾,您決定要向用戶顯示什么,并配置相應(yīng)的OpenGL ES對(duì)象(如頂點(diǎn)緩沖區(qū)對(duì)象皇拣,紋理严蓖,著色器程序及其輸入變量)以上傳到GPU。 接下來(lái)氧急,您提交繪圖指令颗胡,告訴GPU如何使用這些資源來(lái)渲染幀。
OpenGL ES Design Guidelines中更詳細(xì)地介紹了渲染器設(shè)計(jì)吩坝。 現(xiàn)在毒姨,要注意的最重要的性能優(yōu)化是,只有在渲染新幀的開(kāi)始時(shí)钉寝,您的應(yīng)用程序才能更快地修改OpenGL ES對(duì)象弧呐。 雖然您的應(yīng)用程序可以在修改對(duì)象和提交繪圖命令(如上圖中的虛線所示)之間交替,但如果每幀僅執(zhí)行一個(gè)步驟嵌纲,則其運(yùn)行速度更快俘枫。
5. Execute Drawing Commands - 執(zhí)行繪圖命令
此步驟將使用您在上一步中準(zhǔn)備的對(duì)象,并提交繪圖命令以使用它們逮走。 在OpenGL ES Design Guidelines中詳細(xì)介紹了如何將此部分渲染代碼設(shè)計(jì)為高效運(yùn)行鸠蚪。 現(xiàn)在,要注意的最重要的性能優(yōu)化是师溅,如果在開(kāi)始渲染新幀時(shí)僅修改OpenGL ES對(duì)象茅信,則應(yīng)用程序運(yùn)行速度更快。 雖然您的應(yīng)用程序可以在修改對(duì)象和提交繪圖命令(如虛線所示)之間交替墓臭,但如果它只執(zhí)行一次蘸鲸,則運(yùn)行速度更快。
6. Resolve Multisampling - 解決多重采樣
如果您的應(yīng)用程序使用多重采樣來(lái)提高圖像質(zhì)量起便,則應(yīng)用程序必須在呈現(xiàn)給用戶之前解析像素棚贾。 多采樣在Using Multisampling to Improve Image Quality中有詳細(xì)的介紹窖维。
7. Discard Unneeded Renderbuffers - 丟棄不需要的Renderbuffers
丟棄操作是一個(gè)性能提示,它告訴OpenGL ES妙痹,不再需要一個(gè)或多個(gè)渲染緩沖區(qū)的內(nèi)容铸史。 通過(guò)暗示OpenGL ES,您不需要renderbuffer的內(nèi)容怯伊,緩沖區(qū)中的數(shù)據(jù)可以被丟棄琳轿,并且可以避免更新這些緩沖區(qū)內(nèi)容的昂貴任務(wù)。
在渲染循環(huán)的這個(gè)階段耿芹,您的應(yīng)用程序已經(jīng)提交了幀所有繪圖命令崭篡。 當(dāng)您的應(yīng)用程序需要彩色渲染緩沖區(qū)才能顯示到屏幕上時(shí),它可能不需要深度緩沖區(qū)的內(nèi)容吧秕。 下面代碼丟棄了深度緩沖區(qū)的內(nèi)容琉闪。
// Discarding the depth framebuffer
const GLenum discards[] = {GL_DEPTH_ATTACHMENT};
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glDiscardFramebufferEXT(GL_FRAMEBUFFER,1,discards);
注意:glDiscardFramebufferEXT
函數(shù)由OpenGL ES 1.1和2.0的EXT_discard_framebuffer
擴(kuò)展提供。 在OpenGL ES 3.0上下文中砸彬,使用glInvalidateFramebuffer
函數(shù)颠毙。
8. 將結(jié)果呈現(xiàn)給核心動(dòng)畫(huà)
在此步驟中,顏色renderbuffer
保存完成的幀砂碉,所以您需要做的就是將其呈現(xiàn)給用戶蛀蜜。 下面代碼將renderbuffer綁定到上下文并呈現(xiàn)它。 這將導(dǎo)致完成的幀被交給核心動(dòng)畫(huà)增蹭。
// Presenting the finished frame
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER];
默認(rèn)情況下滴某,您必須假定在應(yīng)用程序呈現(xiàn)renderbuffer
后,renderbuffer的內(nèi)容將被丟棄滋迈。 這意味著霎奢,每當(dāng)您的應(yīng)用程序呈現(xiàn)幀時(shí),它必須在渲染新幀時(shí)完全重新創(chuàng)建幀的內(nèi)容杀怠。 由于這個(gè)原因椰憋,上面的代碼總是擦除顏色緩沖區(qū)日矫。
如果您的應(yīng)用程序想要保留幀之間的顏色renderbuffer的內(nèi)容率挣,請(qǐng)將kEAGLDrawablePropertyRetainedBacking
密鑰添加到CAEAGLLayer
對(duì)象的drawableProperties
屬性中存儲(chǔ)的字典中,并從較早的glClear函數(shù)調(diào)用中刪除GL_COLOR_BUFFER_BIT
常量颂暇。 保留的背景可能需要iOS才能分配額外的內(nèi)存來(lái)保留緩沖區(qū)的內(nèi)容硕旗,這可能會(huì)降低應(yīng)用程序的性能窗骑。
Using Multisampling to Improve Image Quality - 使用多重采樣來(lái)提高圖像質(zhì)量
多采樣是一種抗鋸齒形式,可以在大多數(shù)3D應(yīng)用程序中平滑鋸齒狀邊緣并提高圖像質(zhì)量漆枚。 OpenGL ES 3.0包括多采樣作為核心規(guī)范的一部分创译,iOS通過(guò)APPLE_framebuffer_multisample
擴(kuò)展在OpenGL ES 1.1和2.0中提供。 多采樣使用更多的內(nèi)存和片段處理時(shí)間來(lái)渲染圖像墙基,但它可以以比使用其他方法更低的性能成本來(lái)提高圖像質(zhì)量软族。
下圖顯示了多重采樣的工作原理刷喜。 而不是創(chuàng)建一個(gè)幀緩沖區(qū)對(duì)象,您的應(yīng)用程序?qū)?chuàng)建兩個(gè)立砸。 多重采樣緩沖區(qū)包含渲染內(nèi)容所需的所有附件(通常為彩色和深度緩沖區(qū))掖疮。 解析緩沖區(qū)僅包含向用戶顯示渲染圖像所必需的附件(通常為彩色渲染緩沖區(qū),但可能是紋理)颗祝,使用“創(chuàng)建幀緩沖區(qū)對(duì)象”中的相應(yīng)過(guò)程創(chuàng)建浊闪。 多重采樣渲染緩沖區(qū)使用與解析幀緩沖區(qū)相同的維度進(jìn)行分配,但每個(gè)都包含一個(gè)附加參數(shù)螺戳,該參數(shù)指定為每個(gè)像素存儲(chǔ)的采樣數(shù)搁宾。 您的應(yīng)用程序?qū)⑵渌袖秩緢?zhí)行到多重采樣緩沖區(qū),然后通過(guò)將這些樣本解析為解析緩沖區(qū)來(lái)生成最終的抗鋸齒圖像倔幼。
下面代碼顯示了創(chuàng)建多采樣緩沖區(qū)的代碼盖腿。 此代碼使用先前創(chuàng)建的緩沖區(qū)的寬度和高度。 它調(diào)用glRenderbufferStorageMultisampleAPPLE
函數(shù)為renderbuffer
創(chuàng)建多采樣存儲(chǔ)损同。
glGenFramebuffers(1, &sampleFramebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, sampleFramebuffer);
glGenRenderbuffers(1, &sampleColorRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, sampleColorRenderbuffer);
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_RGBA8_OES, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, sampleColorRenderbuffer);
glGenRenderbuffers(1, &sampleDepthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, sampleDepthRenderbuffer);
glRenderbufferStorageMultisampleAPPLE(GL_RENDERBUFFER, 4, GL_DEPTH_COMPONENT16, width, height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, sampleDepthRenderbuffer);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
以下是修改渲染代碼以支持多采樣的步驟:
- 在清除緩沖區(qū)步驟中奸忽,清除多重采樣幀緩沖區(qū)的內(nèi)容。
glBindFramebuffer(GL_FRAMEBUFFER, sampleFramebuffer);
glViewport(0, 0, framebufferWidth, framebufferHeight);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- 提交繪圖命令后揖庄,可將多重采樣緩沖區(qū)中的內(nèi)容解析為解析緩沖區(qū)。 為每個(gè)像素存儲(chǔ)的樣本被合并到解析緩沖區(qū)中的單個(gè)樣本中欠雌。
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, resolveFrameBuffer);
glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, sampleFramebuffer);
glResolveMultisampleFramebufferAPPLE();
- 在丟棄步驟中蹄梢,您可以丟棄附加到多重采樣幀緩沖區(qū)的兩個(gè)renderbuffer。 這是因?yàn)槟?jì)劃呈現(xiàn)的內(nèi)容存儲(chǔ)在解析幀緩沖區(qū)中富俄。
const GLenum discards[] = {GL_COLOR_ATTACHMENT0,GL_DEPTH_ATTACHMENT};
glDiscardFramebufferEXT(GL_READ_FRAMEBUFFER_APPLE,2,discards);
- 在呈現(xiàn)結(jié)果步驟中禁炒,您將呈現(xiàn)附加到解析幀緩沖區(qū)的顏色renderbuffer。
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER];
多次采樣不是免費(fèi)的霍比,需要額外的內(nèi)存來(lái)存儲(chǔ)附加樣本幕袱,并將樣本解析為解析幀緩沖區(qū)需要時(shí)間。 如果您向應(yīng)用程序添加多重采樣悠瞬,請(qǐng)始終測(cè)試應(yīng)用程序的性能们豌,以確保其仍然可以接受。
注意:上述代碼假定為OpenGL ES 1.1
或2.0
上下文浅妆。 多采樣是OpenGL ES 3.0 API
核心的一部分望迎,但函數(shù)不同。 詳見(jiàn)規(guī)范凌外。
后記
未完辩尊,待續(xù)~~~~