美文网首页程序员
OpenGLES-03 使用索引绘制矩形

OpenGLES-03 使用索引绘制矩形

作者: _清墨 | 来源:发表于2017-11-06 18:31 被阅读306次

    这篇文章我们同样借助上篇文章《OpenGLES-02 绘制基本图元(点、线、三角形)》的代码,使用另外一种画法来绘制一个矩形。

    修改render方法如下:

    -(void)render
    {
        //设置清屏颜色,默认是黑色,如果你的运行结果是黑色,问题就可能在这儿
        glClearColor(0.3, 0.5, 0.8, 1.0);
        /*
        glClear指定清除的buffer
        共可设置三个选项GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT
        也可组合如:glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        这里我们只用了color buffer,所以只需清除GL_COLOR_BUFFER_BIT
         */
        glClear(GL_COLOR_BUFFER_BIT);
        
        // Setup viewport
        glViewport(0, 0, self.frame.size.width, self.frame.size.height);
        
        GLfloat vertices[] = {
            // 第一个三角形
            0.5f, 0.5f, 0.0f,   // 右上角
            0.5f, -0.5f, 0.0f,  // 右下角
            -0.5f, 0.5f, 0.0f,  // 左上角
            // 第二个三角形
            0.5f, -0.5f, 0.0f,  // 右下角
            -0.5f, -0.5f, 0.0f, // 左下角
            -0.5f, 0.5f, 0.0f   // 左上角
        };
        
        glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices);
        glEnableVertexAttribArray(_positionSlot);
        
        glDrawArrays(GL_TRIANGLES, 0, 6);
        [_context presentRenderbuffer:_renderBuffer];
    }
    
    运行结果.png

    如上代码所示,我们绘制的矩形是由2个三角形组成的,一个三角形3个顶点,共使用了6个顶点,其中第2个顶点与第4个顶点相同(0.5,-0.5,0.0),第3个顶点与第6个顶点相同(-0.5,0.5,0.0)。
    其实对于矩形来说,它只有4个而不是6个顶点,绘制这个矩形,我们指定了右下角和左上角两次,这样就产生了50%的额外开销。还好我们这会儿只要画一个矩形,当我们要画成千上万个矩形或者别的多边形的时候,这样的绘制方法产生的额外消耗会更多从而产生一大堆浪费。
    更好的解决方案是只储存不同的顶点,并设定绘制这些顶点的顺序。这样子我们只要储存4个顶点就能绘制矩形了,之后只要指定绘制的顺序就行了。还好OpenGL有这样的方式:

    glDrawElements();
    
    glDrawElements 函数的原型为:glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
    
    第一个参数 mode 为描绘图元的模式,其有效值为:GL_POINTS, GL_LINES, GL_LINE_STRIP,  GL_LINE_LOOP,  GL_TRIANGLES,  GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN。这些模式具体含义下面有介绍。
    
    第二个参数 count 为顶点索引的个数也就是,type 是指顶点索引的数据类型,因为索引始终是正值,索引这里必须是无符号型的非浮点类型,因此只能是 GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT 之一,为了减少内存的消耗,尽量使用最小规格的类型如 GL_UNSIGNED_BYTE。
    
    第三个参数 indices 是存放顶点索引的数组。(indices 是 index 的复数形式,3D 里面很多单词的复数都挺特别的。)
    

    索引缓冲对象(简称EBO)的工作方式正是这样的。和顶点缓冲对象一样,EBO也是一个缓冲,它专门储存索引,OpenGL调用这些顶点的索引来决定该绘制哪个顶点。所谓的索引绘制(Indexed Drawing)正是我们问题的解决方案。首先,我们先要定义(独一无二的)顶点,和绘制出矩形所需的索引:

    GLfloat vertices[] = {
        0.5f, 0.5f, 0.0f,   // 右上角
        0.5f, -0.5f, 0.0f,  // 右下角
        -0.5f, -0.5f, 0.0f, // 左下角
        -0.5f, 0.5f, 0.0f   // 左上角
    };
    
    GLubyte indices[] = { // 注意索引从0开始! 
        0, 1, 3, // 第一个三角形
        1, 2, 3  // 第二个三角形
    };
    

    然后整个render函数的代码该是这样的:

    -(void)render
    {
        //设置清屏颜色,默认是黑色,如果你的运行结果是黑色,问题就可能在这儿
        glClearColor(0.3, 0.5, 0.8, 1.0);
        /*
        glClear指定清除的buffer
        共可设置三个选项GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT
        也可组合如:glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        这里我们只用了color buffer,所以只需清除GL_COLOR_BUFFER_BIT
         */
        glClear(GL_COLOR_BUFFER_BIT);
        
        // Setup viewport
        glViewport(0, 0, self.frame.size.width, self.frame.size.height);
     
        GLfloat vertices[] = {
            0.5f, 0.5f, 0.0f,   // 右上角
            0.5f, -0.5f, 0.0f,  // 右下角
            -0.5f, -0.5f, 0.0f, // 左下角
            -0.5f, 0.5f, 0.0f   // 左上角
        };
        
        GLubyte indices[] = { // 注意索引从0开始!
            0, 1, 3, // 第一个三角形
            1, 2, 3  // 第二个三角形
        };
        
        glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices);
        glEnableVertexAttribArray(_positionSlot);
        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, indices);  //6表示有6个索引数据,可以使用sizeof(indices)/sizeof(GLubyte)来确定
        
        [_context presentRenderbuffer:_renderBuffer];
    }
    

    两种方式的运行结果是一样的,我们可以发现,运行图中的矩形是个长方形,而我们给的坐标,照理来讲应该是正方形的,这是因为屏幕的宽高比不同,对应的openGL坐标x、y坐标也不一样,后面我们会讲到投影矩阵,投影矩阵能修复这个问题。

    所有教程代码在此 : https://github.com/qingmomo/iOS-OpenGLES-

    相关文章

      网友评论

        本文标题:OpenGLES-03 使用索引绘制矩形

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