一·什么是OpenGL ES?
? ? ? ? 先說一下OpenGL,它被定義為是一個(gè)跨平臺(tái)和跨編程語言的圖形程序接口API。當(dāng)你要處理高性能圖形繪制的時(shí)候,它是最后的殺手锏。當(dāng)然,因?yàn)槭亲畹讓拥臇|西。所以使用起來也非常的復(fù)雜。
?? ? ? OpenGL ES 是OpenGL 的一個(gè)子集。是現(xiàn)代移動(dòng)設(shè)備繪圖功能的基礎(chǔ)。OpenGL ES定義了嵌入式3D繪圖的標(biāo)準(zhǔn)。在iOS5中蘋果引入了一個(gè)GLKit框架,這個(gè)框架簡(jiǎn)化了很多常用的編程如任務(wù),隱藏了OpenGL ES版本間的差異,使用這個(gè)框架可以用提高軟件開發(fā)的生產(chǎn)效率。下面我們會(huì)通過一個(gè)例子來展示GLKit的神奇之處。
二·幀緩存和像素顏色緩存
? ? ? ?幀緩存:GPU要知道應(yīng)該在內(nèi)存中的哪個(gè)位置存儲(chǔ)已經(jīng)渲染出來的圖像像素?cái)?shù)據(jù)。接受渲染結(jié)果的緩存區(qū)叫做幀緩存。(frame buffer object)
? ? ? ?像素顏色緩存:幀緩存會(huì)保存OpenGL ES的渲染結(jié)果,因此為了渲染到一個(gè)CoreAnimation層上,程序需要一個(gè)連接到某個(gè)層的幀緩存。簡(jiǎn)言之,每個(gè)程序用足夠的內(nèi)存配置一個(gè)層來保存像素顏色數(shù)據(jù)。幀緩存可以配置多個(gè)叫做渲染緩存的緩存來接受多種類型的輸出。與層分享數(shù)據(jù)的幀緩存必須要有一個(gè)像素顏色渲染緩存。其他緩存是可選的。
這里的概念可能有點(diǎn)模糊。沒關(guān)系。接下來看。相信你會(huì)懂得。
三·Rendering to a Core Animation Layer(渲染到CoreAnimation層)

? ? ? ? ? Core Animation是iOS上圖形渲染和動(dòng)畫的中央基礎(chǔ)架構(gòu)。 您可以使用承載使用不同iOS子系統(tǒng)呈現(xiàn)的內(nèi)容的圖層(例如UIKit,Quartz 2D和OpenGL ES)來構(gòu)建應(yīng)用程序的用戶界面或其他可視化顯示。 OpenGL ES通過CAEAGLLayer類連接到Core Animation,這是一種特殊類型的Core Animation層,其內(nèi)容來自O(shè)penGL ES渲染緩沖區(qū)。Core Animation將renderbuffer(渲染緩存)的內(nèi)容與其他圖層合成,并在屏幕上顯示生成的圖像。
? ? ? ? ? CAEAGLLayer通過提供兩個(gè)關(guān)鍵的功能為OpenGL ES提供這種支持:
? ? ? ? ? 1.為renderbuffer分配共享存儲(chǔ)。
? ? ? ? ? 2.它將渲染緩沖區(qū)呈現(xiàn)給Core Animation,用渲染緩沖區(qū)的數(shù)據(jù)替換圖層的先前內(nèi)容。
? ? ? ? ? 這個(gè)模型的優(yōu)點(diǎn)是核心動(dòng)畫層的內(nèi)容不需要在每個(gè)幀中繪制,只有當(dāng)渲染的圖像改變時(shí)。
四·代碼解釋
0.創(chuàng)建一個(gè)OpenGLESView,繼承UIView,通過重寫OpenGLESView的 + (Class)layerClass 方法來返回一個(gè)CAEAGLLayer實(shí)例
+ (Class)layerClass {
return [CAEAGLLayer class];
}
1.創(chuàng)建上下文,并設(shè)置當(dāng)前上下文為我們創(chuàng)建的上下文
//創(chuàng)建上下文
EAGLContext *context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
// 設(shè)置當(dāng)前上下文為我們創(chuàng)建的上下文
[EAGLContext setCurrentContext:_context];
2.創(chuàng)建CAEAGLLayer對(duì)象并配置其屬性。
為了獲得最佳性能,請(qǐng)將圖層的opaque屬性的值設(shè)置為YES。
CAEAGLLayer *_eagllayer;
_eagllayer = (CAEAGLLayer *)self.layer;
_eagllayer.opaque = YES;
//設(shè)置描述屬性
//kEAGLDrawablePropertyRetainedBacking保留背景,NO表示在屏幕上顯示繪制整個(gè)內(nèi)容
//kEAGLColorFormatRGBA8告訴coreAnimation用8位來保存層內(nèi)的每個(gè)像素的每個(gè)顏色元素的值
_eagllayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [NSNumber numberWithBool:NO],kEAGLDrawablePropertyRetainedBacking,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? kEAGLColorFormatRGBA8,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? kEAGLDrawablePropertyColorFormat, nil];
3.創(chuàng)建并綁定一個(gè) 幀緩存(frame buffer object)
GLuint _framebuffer; //緩存標(biāo)識(shí)符
glGenFramebuffers(1,&_framebuffer);? //第一個(gè)參數(shù):指定要生成的緩存標(biāo)識(shí)符的數(shù)量,第二個(gè)參數(shù):是一個(gè)指針,指向生成的標(biāo)識(shí)符的內(nèi)存保存位置
glBindFramebuffer(GL_FRAMEBUFFER, _framebuffer); //把新創(chuàng)建的幀緩沖(_framebuffer)綁定到GL_FRAMEBUFFER目標(biāo)上
4.創(chuàng)建并綁定一個(gè) 像素顏色渲染緩存,跟創(chuàng)建幀緩存差不多
GLuint _colorRenderbuffer;
glGenRenderbuffers(1,&_colorRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER,_colorRenderbuffer); //將_colorRenderbuffer綁定到GL_RENDERBUFFER目標(biāo)上
5.上面我們已經(jīng)創(chuàng)建了一個(gè)像素顏色渲染緩存(_colorRenderbuffer),通過調(diào)用是上下文的renderbufferStorage:fromDrawable:方法并傳遞圖層對(duì)象作為參數(shù)來分配它的存儲(chǔ)。 寬度,高度和像素格式取自圖層,用于為_colorRenderbuffer分配存儲(chǔ)空間
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eagllayer];
5.將像素顏色渲染緩存附加到幀緩沖的顏色附件點(diǎn)上
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);
6.清屏操作
glClearColor(0.0f,0.0f,0.0f,1.0f) //指定清屏的顏色,你可以認(rèn)為是設(shè)置背景顏色
//用指定的清屏顏色來清除由mask指定的buffer
//mask 可以是 GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT的自由組合。
glClear(mask);
7.將結(jié)果呈現(xiàn)給CoreAnimation?
將_colorRenderbuffer綁定到上下文并呈現(xiàn)它。 這使得完成的幀被交給核心動(dòng)畫。
glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderbuffer);
[context presentRenderbuffer:GL_RENDERBUFFER];
8.清理緩存
glDeleteFramebuffers(1, &_frameBuffer);
_frameBuffer =0;
glDeleteRenderbuffers(1, &_colorRenderbuffer);
_colorRenderbuffer =0;
到這里,我們通過自定義圖層CAEAGLLayer來實(shí)現(xiàn)了渲染。我們看下效果圖。

GLKit框架是為了簡(jiǎn)化iOS上OpenGL ES的開發(fā),同樣的實(shí)現(xiàn)上面相同的效果,GLKit只需要寥寥幾句就可以完成。。
1.導(dǎo)入GLKit框架,創(chuàng)建一個(gè)GLKitController繼承 GLKViewController,
2.設(shè)置GLKView的上下文,GLKView是Cocoa Touch UIView類的內(nèi)建子類。GLKView簡(jiǎn)化了通過用CoreAnimation層來自動(dòng)創(chuàng)建并管理幀緩存和渲染緩存共享內(nèi)存所需要做的工作
GLKView *view = (GLKView *)self.view;
view.context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:view.context];
3.指定清屏顏色
glClearColor(0.5f, 0.5f, 1.0f, 1.0f);
4.實(shí)現(xiàn)- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect代理,實(shí)現(xiàn)渲染。
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
glClear(GL_COLOR_BUFFER_BIT);
}
到此。結(jié)束。運(yùn)行。一樣的效果。
參考文獻(xiàn)
《蘋果開發(fā)文檔》?
《OpenGL ES應(yīng)用開發(fā)實(shí)踐指南》
http://blog.csdn.net/icetime17/article/details/50429658
http://www.itdecent.cn/p/750fde1d8b6a