前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenGLES-03 使用索引绘制矩形

OpenGLES-03 使用索引绘制矩形

作者头像
清墨
发布2018-05-07 16:01:02
1.1K0
发布2018-05-07 16:01:02
举报
文章被收录于专栏:清墨_iOS分享清墨_iOS分享

这篇文章我们同样借助上篇文章《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-

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017.11.06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档