美文网首页
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