美文网首页
OpenGL ES 索引绘图

OpenGL ES 索引绘图

作者: _涼城 | 来源:发表于2020-08-02 12:57 被阅读0次

传统绘图与索引绘图的区别

我们使用传统的数组绘制方式绘制一个立方体时,可能每个面使用6个顶点(绘制两个三角形),其中2个顶点是共享的,重复的上个月专业户,那么一共需要制定36个顶点;如果使用索引绘图的话,不需要为重复的顶点再分配内存,实际上只需要24个顶点数据。

索引绘图

为了在多个三角形之间共享属性数据,我们需要通过索引数组对属性数组进行访问。

索引绘制需要做两件事:一个构造良好的索引数组和一个新的索引绘制命令。

索引数组

索引数组,存储在缓存对象中,它有一个特别的缓存对象,GL_ELEMENT_ARRAY_BUFFER. 你可以使用这个缓存对象来作为正常的缓存对象使用,就像GL_ARRAY_BUFFER。但是对于OpenGL他有特殊含义,那就是索引绘图必须使用这个缓存对象。

索引绘制命令

为了进行索引绘图,我们需要将索引数组绑定到GL_ELEMENT_ARRAY_BUFFER,然后调用glDrawElements

//使用索引绘图
/*
 void glDrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices);
 参数列表:
 mode:要呈现的画图的模型 
            GL_POINTS
            GL_LINES
            GL_LINE_LOOP
            GL_LINE_STRIP
            GL_TRIANGLES
            GL_TRIANGLE_STRIP
            GL_TRIANGLE_FAN
 count:绘图个数
 type:类型
         GL_BYTE
         GL_UNSIGNED_BYTE
         GL_SHORT
         GL_UNSIGNED_SHORT
         GL_INT
         GL_UNSIGNED_INT
 indices:绘制索引数组

 */
glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(indices[0]), GL_UNSIGNED_INT, indices);
金字塔绘图图解
  1. 顶点数据
    顶点数据.jpg
  2. 金字塔底部
    金字塔底部索引数据.jpg
  3. 金字塔四侧
    金字塔四侧索引信息.jpg
使用给定索引数组方式实现索引绘图方式
顶点着色器代码
attribute vec4 position;
attribute vec4 positionColor;

uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;

varying lowp vec4 varyColor;

void main()
{
    varyColor = positionColor;

    vec4 vPos;

    //4*4 * 4*4 * 4*1
    vPos = projectionMatrix * modelViewMatrix * position;

    //ERROR
    //vPos = position * modelViewMatrix  * projectionMatrix ;
    gl_Position = vPos;
}
片元着色器代码
varying lowp vec4 varyColor;
void main()
{
    gl_FragColor = varyColor;
}
渲染流程
GLSL自定义着色器索引绘制流程.jpg
渲染部分核心代码
 GLfloat attrArr[] =
    {
        -0.5f, 0.5f, 0.0f,      1.0f, 0.0f, 1.0f, //左上0
        0.5f, 0.5f, 0.0f,       1.0f, 0.0f, 1.0f, //右上1
        -0.5f, -0.5f, 0.0f,     1.0f, 1.0f, 1.0f, //左下2

        0.5f, -0.5f, 0.0f,      1.0f, 1.0f, 1.0f, //右下3
        0.0f, 0.0f, 1.0f,       0.0f, 1.0f, 0.0f, //顶点4
    };

    //(2).索引数组
    GLuint indices[] =
    {
        0, 3, 2,
        0, 1, 3,
        0, 2, 4,
        0, 4, 1,
        2, 3, 4,
        1, 4, 3,
    };

    //(3).判断顶点缓存区是否为空,如果为空则申请一个缓存区标识符
    if (self.myVertices == 0) {
        glGenBuffers(1, &_myVertices);
    }
    //9.-----处理顶点数据-------
    //(1).将_myVertices绑定到GL_ARRAY_BUFFER标识符上
    glBindBuffer(GL_ARRAY_BUFFER, _myVertices);
    //(2).把顶点数据从CPU内存复制到GPU上
    glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_DYNAMIC_DRAW);

    GLuint position = glGetAttribLocation(self.myProgram, "position");

    glEnableVertexAttribArray(position);

    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, NULL);
    GLuint positionColor = glGetAttribLocation(self.myProgram, "positionColor");
    glEnableVertexAttribArray(positionColor);

    glVertexAttribPointer(positionColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 6, (GLfloat *) NULL + 3 );

    GLuint projectionMatrix = glGetUniformLocation(self.myProgram, "projectionMatrix");

    GLuint modelViewMatrix = glGetUniformLocation(self.myProgram, "modelViewMatrix");

    float width = self.frame.size.width;
    float height = self.frame.size.height;

    float aspect = width/ height;
    GLKMatrix4 _projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(30.f), aspect, 5.0f, 20.0);
    _projectionMatrix = GLKMatrix4Scale(_projectionMatrix, 1.0f, 1.0f, 1.0f);

    glUniformMatrix4fv(projectionMatrix, 1, false, (GLfloat *)&_projectionMatrix.m00);

    GLKMatrix4 _modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, -10.0f);

    GLKMatrix4 _rotationMatrix = GLKMatrix4Rotate(GLKMatrix4Identity, GLKMathDegreesToRadians(xDegree), 1.0, 0.0, 0.0);
    _rotationMatrix = GLKMatrix4Rotate(_rotationMatrix, GLKMathDegreesToRadians(yDegree), 0.0, 1.0, 0.0);
    _rotationMatrix = GLKMatrix4Rotate(_rotationMatrix, GLKMathDegreesToRadians(zDegree), 0.0, 0.0, 1.0);

    GLKMatrix4 _lastMatrix = GLKMatrix4Multiply(_modelViewMatrix, _rotationMatrix);

    glUniformMatrix4fv(modelViewMatrix, 1, false, (GLfloat *)&_lastMatrix.m00);
    glEnable(GL_CULL_FACE);
    //
    glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(indices[0]), GL_UNSIGNED_INT, indices);

    [self.myContext presentRenderbuffer:GL_RENDERBUFFER];
使用索引缓冲区方式实现索引绘图
  1. 将索引数组存储到索引缓冲区
  //将索引数组存储到索引缓冲区 GL_ELEMENT_ARRAY_BUFFER
    GLuint index;
    glGenBuffers(1, &index);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
  1. 绘制时,绘制索引数组置为0
    glDrawElements(GL_TRIANGLES, self.count, GL_UNSIGNED_INT, 0);
    

相关文章

网友评论

      本文标题:OpenGL ES 索引绘图

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