OpenGL ES之绘制三角形(一)

作者: 冰三尺 | 来源:发表于2017-07-03 15:17 被阅读266次

    这里是OpenGL ES第一次上手, 文章的目的是实现绘制一个三角形

    GLKView是一个使用OpenGL ES进行绘图的默认实现, GLKView简化了绘图的配置

    实现一个绘图需要7个步骤
    1. 为缓存生成一个独
    2. 为接下来的运算绑
    3. 复制数组到缓存
    4. 启动
    5. 设置指针
    6. 绘图
      7)释放资源
    //本例中使用的事从storyboard中加载, 所以需要把Main.storyboard的类关联到GLKViewController
    @interface ViewController : GLKViewController
    {
       GLuint vertexBufferID; //顶点数据缓存的标识符
    }
    
    //GLKBaseEffect是GLKit提供的一个内建类, GLKBaseEffect的存在是为了简化很多OpenGL ES 的常用操作, GLKBaseEffect隐藏了多个iOS版本对OpenGL ES支持的差异,  
    @property (strong, nonatomic) GLKBaseEffect *baseEffect;
    
    @end
    
    //定义一个C语言的结构体SceneVertex, 用于保存GLKVector3数据, 顶点的坐标可以用一个起始于远点的矢量来表示
    typedef struct {
       GLKVector3  positionCoords;
    }SceneVertex;
    
    
    //vertices变量是一个用顶点数据初始化的C语言的数组, 这个变量用于定义一个三角形
    static const SceneVertex vertices[] =
    {
       {{-0.5f, -0.5f, 0.0}}, 
       {{ 0.5f, -0.5f, 0.0}}, 
       {{-0.5f,  0.5f, 0.0}}  
    };
    

    OpenGL ES的坐标和UIView的坐标是不一样的, 下图展示的及时上面定义的三角形的坐标

    屏幕快照 2017-07-03 下午1.59.36.png

    设置OpenGL ES上线下文

    - (void)setEGALContext {
       //创建一个GLKView
       GLKView *view = (GLKView *)self.view;
       NSAssert([view isKindOfClass:[GLKView class]],
                @"View controller's view is not a GLKView");
       
       //初始化EAGLContext上线文, 给GLKView绑定EAGL
       /**
        * kEAGLRenderingAPIOpenGLES2代表的事OpenGL ES 2.0
        */
       view.context = [[EAGLContext alloc]
                       initWithAPI:kEAGLRenderingAPIOpenGLES2];
       
       //给当前的OpenGL ES设置将会用到的上下文
       [EAGLContext setCurrentContext:view.context];
    
    }
    

    GLKBaseEffect提供了不依赖于所使用的OpenGL ES版本的控制OpenGL ES 渲染的方法
    如果没有GLKBaseEffect和GLKit类, 完成这个简单的例子需要在OpenGL ES 2.0 的Shading Language编写一个小的GPU程序, GLKBaseEffect会在需要的时候自动创建GPU程序

    - (void)setBaseEffect {
        self.baseEffect = [[GLKBaseEffect alloc] init];
        self.baseEffect.useConstantColor = GL_TRUE;
        //控制渲染颜色的方式有很多种, 下面是一个恒定的白色三角形, 使用一个保存颜色四个元素的结构体来设置恒定的颜色
        //颜色格式为RGBA
        GLKVector4 vector4 = GLKVector4Make(
                                            1.0f,
                                            1.0f,
                                            1.0f,
                                            1.0f);
        
        self.baseEffect.constantColor = vector4;
    
    }
    

    创建并使用一个用于保存顶点数据的顶点属性数组缓存, 主要用于CPU控制的内存与GPU控制的内存之间的数据交换的唯一标识符

       1) 为缓存生成一个独一无二的标识符
       2) 为接下来的运算绑定缓存
       3) 复制数组到缓存
    
    - (void)setBufferData {    
        //glGenBuffers用于生成一个独一无二的标识符, 第一个参数指定要生成的缓存的数量为1, 第二个参数指向生成标识符的内存地址, 并保存. 当前情况下, 一个标识符被生成并保存在vertexBufferID实例变量中
        glGenBuffers(1,                // STEP 1
                     &vertexBufferID);
        
        //glBindBuffer函数用于绑定指定标识符的缓存到当前的缓存, OpenGL ES 保存不同类型的缓存到当前上下文的不同部位, 但是在同一时刻只能绑定一个缓存
        //第一个参数是一个常亮, 用于指定缓存的类型, GL_ARRAY_BUFFER类型用于指定一个顶点属性数组, 三角形就是属于这种类型, 第二个参数是要绑定的标识符
        glBindBuffer(GL_ARRAY_BUFFER,  // STEP 2
                     vertexBufferID);
        
        //glBufferData函数复制应用的顶点数据到当前上下文绑定顶点的缓存中
        glBufferData(                  // STEP 3
                     GL_ARRAY_BUFFER,  // 指定当前上下文所绑定的是哪一个缓存
                     sizeof(vertices), // 复制到这个缓存的字节数
                     vertices,         // 要复制的字节的地址
                     GL_STATIC_DRAW);  // 提示缓存在未来会被怎样的使用, GL_STATIC_DRAW会提示上下文缓存中的内容适合复制到GPU控制的内存, 对其很少修改, 这个信息会提示OpenGL ES来优化内存使用
    }
    
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        [self setEGALContext];
        
        [self setBaseEffect];
        
        //glClearColor函数用于设置当前上下文的清除颜色, 由RGBA组成, 用于在上下文的帧缓存被清除时初始化每个像素的颜色值
        glClearColor(0.5f, 0.5f, 0.5f, 1.0f); // background color
        
        [self setBufferData];
    }
    

    所有的配置结束之后, 下面开始执行绘图
    GLKViewControllerDelegate的代理在配置工作完成之后会自动执行绘图

    • (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
    //该方法是GLKView的委托方法, 实现该方法就意味着要告诉GLKBaseEffect去准备号OpenGL ES上下文
    - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
     {
         [self.baseEffect prepareToDraw];
         
         //清除之前设置的值, 使用glClearColor设置的值
         //注意:  该glClear功能提示OpenGL ES可以丢弃任何现有的帧缓冲区内容,避免了将先前内容加载到内存中的昂贵的内存操作。为确保最佳性能,您应该在绘制之前始终调用此函数。
         glClear(GL_COLOR_BUFFER_BIT);
         
         /**
          * 4) 启动
          * 5) 设置指针
          * 6) 绘图
          */
         //该方法用于启动顶点缓存的渲染操作,
         glEnableVertexAttribArray(      // STEP 4
                                   GLKVertexAttribPosition);
         
         //该方法会告诉OpenGL ES 顶点数据在哪里. 以及怎么解释顶点数据,
         glVertexAttribPointer(          // STEP 5
                               GLKVertexAttribPosition,  //当前绑定的缓存包含每个顶点的位置信息
                               3,                   // 每个顶点位置有几个部分
                               GL_FLOAT,            // 告诉OpenGL ES 每个顶点位置都为一个浮点类型的值
                               GL_FALSE,            // 告诉OpenGL ES 小数点固定数据是否可以被改变
                               sizeof(SceneVertex), // 每个顶点的保存需要多少个字节
                               NULL);               // NULL 告诉 OpenGL ES 可以从当前绑定的顶点缓存的开始位置访问顶点数据
         
         
         //执行绘图
         // STEP 6
         glDrawArrays(GL_TRIANGLES, //告诉GPU 如何去处理绑定在顶点缓存内的顶点数据, 该参数是渲染一个三角形
                      0,  // 要渲染的第一个顶点的位置
                      3); // 要渲染的顶点的数量
     }
    

    在我们不需要执行程序时, 别忘记释放资源

    - (void)dealloc {
        //获取当前的GLKView
        GLKView *view = (GLKView *)self.view;
        [EAGLContext setCurrentContext:view.context];
        
        /**
         * 7)释放资源
         */
        //删除不在需要的顶点缓存和上下文
        if (0 != vertexBufferID)
        {
            glDeleteBuffers (1,          // STEP 7
                             &vertexBufferID);
            vertexBufferID = 0; //设置为0避免在对应的缓存被删除之后存在未被使用的无效标识符
        }
        
        ((GLKView *)self.view).context = nil; //设置视图的上下文属性为nil
        [EAGLContext setCurrentContext:nil]; //设置当前上下文的属性为nil
        
    }
    

    运行之后的效果

    Simulator Screen Shot 2017年7月3日 下午3.22.52.png

    相关文章

      网友评论

      • 不辣先生:glkview 可以不是控制器的view吗?比如我在self.view添加一个子view然后在子view上面绘制,因为我想通过该view实现大小的改变和位置的变化,动画

      本文标题:OpenGL ES之绘制三角形(一)

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