美文网首页
从零开始学习OpenGL ES(2)--使用GLKit渲染一张图

从零开始学习OpenGL ES(2)--使用GLKit渲染一张图

作者: 那时J花开 | 来源:发表于2019-03-20 15:33 被阅读0次

    上一篇文章中, 我们学习了OpenGL ES中的一些基本概念, 从这篇文章开始, 将一起学习, 如何通过OpenGL ES去渲染图形.

    一、GLKit

    GLKit是iOS 5引入的一个为简化OpenGL ES的使用的框架,它对OpenGL ES的函数进行了封装并提供了相关的类和函数,GLKit是Cocoa Touch以及多个其他的框架(包含UIKit)的一部分。而GLKViewGLKViewController类名字中的GLK前缀表明这些类是GLKit框架的一部分。

    今天学习如何用GLView来渲染一张图片:

    1. 获取顶点数据

    首先定义一个结构体,用来保存顶点数据. 用一个三维向量来保存(x,y,z)坐标, 一个二维向量来保存(u,v)坐标

    /**
     定义顶点类型
     */
    typedef struct {
        GLKVector3 positionCoord; // (X, Y, Z)
        GLKVector2 textureCoord; // (U, V)
    } CustomVertexInfo;
    

    定义一个顶点数组, 来保存4个顶点:

    @property (nonatomic, assign) CustomVertexInfo *verticesArray; //!< 顶点数组
    

    初始化顶点数据:

        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, 设置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];
        
        //!< 设置 glkView 的上下文为当前上下文
        [EAGLContext setCurrentContext:self.glkView.context];
    
    3. 获取图片, 并用GLKTextureLoader来加载纹理数据
    //!< 通过 GLKTextureLoader 来加载纹理,并存放在 GLKBaseEffect 中
        NSString *imagePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"example.jpg"];
        UIImage *image = [UIImage imageWithContentsOfFile:imagePath]; 
        NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft : @(YES)}; //!< 消除 UIKit 和 GLKit 的坐标差异,否则会上下颠倒
        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. 实现GLKView的代理方法- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect, 并在代理方法中按照上一篇文章中的使用缓存的7个步骤, 来绘制图片
    - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
        [self.baseEffect prepareToDraw];
        
        //!< 创建顶点缓存
        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:缓存数据
        
        //!< 设置顶点数据
        glEnableVertexAttribArray(GLKVertexAttribPosition);  // !< 4:启用或禁用
        glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(CustomVertexInfo), NULL + offsetof(CustomVertexInfo, positionCoord)); // !< 5:设置指针
        
        //!< 设置纹理数据
        glEnableVertexAttribArray(GLKVertexAttribTexCoord0);  // !< 4:启用或禁用
        glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(CustomVertexInfo), NULL + offsetof(CustomVertexInfo, textureCoord)); // !< 5:设置指针
        
        //!< 开始绘制
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);  // !< 6:绘图
        
        //!< 删除顶点缓存
        glDeleteBuffers(1, &vertexBuffer);  // !< 7:删除
        vertexBuffer = 0;
    }
    
    6. dealloc时释放内存, 清空EAGLContext当前上下文
    - (void)dealloc {
        if ([EAGLContext currentContext] == self.glkView.context) {
            [EAGLContext setCurrentContext:nil];
        }
        if (_verticesArray) {
            free(_verticesArray);
            _verticesArray = nil;
        }
    }
    

    最终效果如图:


    GLKViewRender

    相关文章

      网友评论

          本文标题:从零开始学习OpenGL ES(2)--使用GLKit渲染一张图

          本文链接:https://www.haomeiwen.com/subject/fnzzmqtx.html