從零開始學(xué)習(xí)OpenGL ES(2)--使用GLKit渲染一張圖片

上一篇文章中, 我們學(xué)習(xí)了OpenGL ES中的一些基本概念, 從這篇文章開始, 將一起學(xué)習(xí), 如何通過OpenGL ES去渲染圖形.

一、GLKit

GLKit是iOS 5引入的一個(gè)為簡(jiǎn)化OpenGL ES的使用的框架,它對(duì)OpenGL ES的函數(shù)進(jìn)行了封裝并提供了相關(guān)的類和函數(shù),GLKit是Cocoa Touch以及多個(gè)其他的框架(包含UIKit)的一部分。而GLKViewGLKViewController類名字中的GLK前綴表明這些類是GLKit框架的一部分。

今天學(xué)習(xí)如何用GLView來渲染一張圖片:

1. 獲取頂點(diǎn)數(shù)據(jù)

首先定義一個(gè)結(jié)構(gòu)體,用來保存頂點(diǎn)數(shù)據(jù). 用一個(gè)三維向量來保存(x,y,z)坐標(biāo), 一個(gè)二維向量來保存(u,v)坐標(biāo)

/**
 定義頂點(diǎn)類型
 */
typedef struct {
    GLKVector3 positionCoord; // (X, Y, Z)
    GLKVector2 textureCoord; // (U, V)
} CustomVertexInfo;

定義一個(gè)頂點(diǎn)數(shù)組, 來保存4個(gè)頂點(diǎn):

@property (nonatomic, assign) CustomVertexInfo *verticesArray; //!< 頂點(diǎn)數(shù)組

初始化頂點(diǎn)數(shù)據(jù):

    self.verticesArray = malloc(sizeof(CustomVertexInfo) * 4); 
    
    self.verticesArray[0] = (CustomVertexInfo){{-1, 1, 0}, {0, 1}}; //!< 左上角
    self.verticesArray[1] = (CustomVertexInfo){{-1, -1, 0}, {0, 0}}; //!< 左下角
    self.verticesArray[2] = (CustomVertexInfo){{1, 1, 0}, {1, 1}}; //!< 右上角
    self.verticesArray[3] = (CustomVertexInfo){{1, -1, 0}, {1, 0}}; //!< 右下角
2. 初始化GLKView, 設(shè)置EAGLContext上下文
 //!< 初始化 GLKView
    CGRect frame = CGRectMake(0, 100, self.view.frame.size.width, self.view.frame.size.width); 
    self.glkView = [[GLKView alloc] initWithFrame:frame context:context];
    self.glkView.backgroundColor = [UIColor clearColor];
    self.glkView.delegate = self;
    
    [self.view addSubview:self.glkView];
    
    //!< 設(shè)置 glkView 的上下文為當(dāng)前上下文
    [EAGLContext setCurrentContext:self.glkView.context];
3. 獲取圖片, 并用GLKTextureLoader來加載紋理數(shù)據(jù)
//!< 通過 GLKTextureLoader 來加載紋理,并存放在 GLKBaseEffect 中
    NSString *imagePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"example.jpg"];
    UIImage *image = [UIImage imageWithContentsOfFile:imagePath]; 
    NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft : @(YES)}; //!< 消除 UIKit 和 GLKit 的坐標(biāo)差異,否則會(huì)上下顛倒
    GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithCGImage:[image CGImage]
                                                               options:options
                                                                 error:NULL];
4. 用GLKBaseEffect保存紋理id
    self.baseEffect = [[GLKBaseEffect alloc] init];
    self.baseEffect.texture2d0.name = textureInfo.name;
    self.baseEffect.texture2d0.target = textureInfo.target;
5. 實(shí)現(xiàn)GLKView的代理方法- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect, 并在代理方法中按照上一篇文章中的使用緩存的7個(gè)步驟, 來繪制圖片
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    [self.baseEffect prepareToDraw];
    
    //!< 創(chuàng)建頂點(diǎn)緩存
    GLuint vertexBuffer;
    glGenBuffers(1, &vertexBuffer);  // !< 1:生成
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);  // !< 2:綁定
    GLsizeiptr bufferSizeBytes = sizeof(CustomVertexInfo) * 4;
    glBufferData(GL_ARRAY_BUFFER, bufferSizeBytes, self. verticesArray, GL_STATIC_DRAW);  // !< 3:緩存數(shù)據(jù)
    
    //!< 設(shè)置頂點(diǎn)數(shù)據(jù)
    glEnableVertexAttribArray(GLKVertexAttribPosition);  // !< 4:?jiǎn)⒂没蚪?    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(CustomVertexInfo), NULL + offsetof(CustomVertexInfo, positionCoord)); // !< 5:設(shè)置指針
    
    //!< 設(shè)置紋理數(shù)據(jù)
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);  // !< 4:?jiǎn)⒂没蚪?    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(CustomVertexInfo), NULL + offsetof(CustomVertexInfo, textureCoord)); // !< 5:設(shè)置指針
    
    //!< 開始繪制
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);  // !< 6:繪圖
    
    //!< 刪除頂點(diǎn)緩存
    glDeleteBuffers(1, &vertexBuffer);  // !< 7:刪除
    vertexBuffer = 0;
}
6. dealloc時(shí)釋放內(nèi)存, 清空EAGLContext當(dāng)前上下文
- (void)dealloc {
    if ([EAGLContext currentContext] == self.glkView.context) {
        [EAGLContext setCurrentContext:nil];
    }
    if (_verticesArray) {
        free(_verticesArray);
        _verticesArray = nil;
    }
}

最終效果如圖:


GLKViewRender
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容