示例最終效果
這篇筆記的關鍵在于對OpenGL ES繪圖7個步驟中的函數各個參數的的解讀,筆者之前看別人的文章被這些函數的參數弄的暈頭轉向,看了這本書之后終于理解透徹。
準備
- 首先復習一下為緩存提供數據的7個步驟,可以在第一篇筆記中查看,這里不再贅述。
- iOS中使用OpenGL ES的框架為GLKit,Demo中會使用UIViewController的子類
GLKViewController
作為主控制器,將控制器的view轉換為GLKView
,這樣可以省去設置GLKView代理等操作。
需要注意本例中直接使用默認新建的項目,需要在storyboard中修改ViewController中View的類型為GLKView,需要在ViewController.h中把父類改為GLKViewController。
- 示例概要:
- 準備三角形頂點數據數組
- 設置GLKView的上下文為當前的上下文
- 設置著色器屬性
- 申請、綁定、緩存頂點數據
- 在代理方法中,準備繪圖
- 著色器準備
- 清理
- 啟用緩存頂點數據、設置指針、繪圖
- dealloc方法中刪除緩存數據
示例解說
一、準備頂點數據數組
- 聲明一個結構體保存一個頂點的數據
- 創建一個C數組保存三角形的3個頂點
/** 保存每個頂點的數據 */
typedef struct vector {
GLKVector3 positionCoords;
}SceneVertex;
/** 保存三角形3個頂點的數據 */
static const SceneVertex vertices[] = {
{{-0.5, -0.5, 0}},
{{ 0.5, -0.5, 0}},
{{-0.5, 0.5, 0}}
};
二、設置當前的上下文為view的上下文
/** 強轉view為GLKView,需要在storyboard中也要修改 */
GLKView *view = (GLKView *)self.view;
/** 斷言,判斷view的類型 */
NSAssert([view isMemberOfClass:[GLKView class]], @"View controller's view is not a GLKView");
/** 創建一個OpenGL ES 2.0的上下文給view */
view.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
/** 將view的上下文設置為當前的上下文 */
[EAGLContext setCurrentContext:view.context];
三、設置著色器,三角顏色及背景色
/** 為OpenGL ES 2.0創建一個默認的基本效果并提供給片元著色器程序,用于之后的繪圖渲染 */
_baseEffect = [[GLKBaseEffect alloc] init];
_baseEffect.useConstantColor = GL_TRUE;
_baseEffect.constantColor = GLKVector4Make(200.0, /** 紅 */
0.0, /** 綠 */
0.0, /** 藍 */
1.f); /** alpha */
/** 設置背景色,存儲到當前的上下文中 */
glClearColor(1.0, 1.0, 1.0, 1.0);
四、申請、綁定、緩存
函數的參數說明已經在注釋中寫的非常詳細了!
/** 申請、綁定并初始化一塊緩存,將繪圖信息保存到GPU的當中 */
/** ①申請 */
glGenBuffers(1, /** 指定要生成的緩存標識符的數量 */
&vertexBufferID); /** 指針:緩存標識符的地址 */
/** ②綁定 */
glBindBuffer(GL_ARRAY_BUFFER, /** 綁定什么類型的緩存:頂點屬性數組 */
vertexBufferID); /** 需要綁定的緩存的標識符(標識符為0表示沒有緩存,就不會綁定數據) */
/** ③緩存數據 */
glBufferData(GL_ARRAY_BUFFER, /** 初始化緩存信息 */
sizeof(vertices), /** 緩存需要拷貝的大小 */
vertices, /** 需要拷貝的數據:拷貝數據的地址 */
GL_STATIC_DRAW); /** 提示:告訴上下文緩存適合放到GPU內存中,因為數據很少被更改,可以幫助OpenGL ES優化內存 */
五、開始繪圖
當GLKView需要重新繪制時就會調用代理方法
glkView:drawInRect:
-
在代理方法內,開始準備繪圖工作
/** 準備繪制 */ [_baseEffect prepareToDraw]; /** 清理之前的繪圖 */ glClear(GL_COLOR_BUFFER_BIT);
-
啟用頂點數據、設置指針、開始繪圖
/** ④啟用頂點數據 */ glEnableVertexAttribArray(GLKVertexAttribPosition); /** ⑥設置指針:目的在于告訴OpenGL ES頂點數據在哪里以及解釋每個頂點保存的數據 */ glVertexAttribPointer(GLKVertexAttribPosition, /** 頂點數據 */ 3, /** 每個頂點包含3個數據 */ GL_FLOAT, /** 頂點數據類型 */ GL_FALSE, /** 固定點數據是否歸一化或直接轉固定值:不轉換,直接使用float類型數據,可以幫助OpenGL ES優化內存 */ sizeof(SceneVertex), /** 步幅:從一個頂點到另一個需要跨過多少字節,取單個頂點大小 */ NULL); /** 告訴OpenGL ES可以從當前綁定的頂點緩存的開始位置訪問頂點數據 */ glDrawArrays(GL_TRIANGLES, /** 告訴GPU怎樣渲染緩存內的頂點數據:渲染三角形 */ 0, /** 第一個需要渲染的頂點位置 */ 3); /** 渲染的頂點數量 */
六、最后的清理工作
在dealloc方法中清理緩存
/** 如果有緩存的情況下 */
if (vertexBufferID != 0) {
/** ⑦刪除緩沖區數據 */
glDeleteBuffers(1, &vertexBufferID);
/** 將標識符設置為0 */
vertexBufferID = 0;
}
/** 將當前上下文設置nil */
[EAGLContext setCurrentContext:nil];
小結
- 示例算是OpenGL ES中最簡單的,只是為了熟悉7個步驟而生,旨在熟悉基本的流程、函數及函數的各個參數。
- 代碼會在后續統一上傳到github,其實基本上都貼出來了,當然有需要的可以自行下載。