顶点数组

来源:互联网 发布:携程数据分析师笔试题 编辑:程序博客网 时间:2024/04/23 19:14

一、顶点数组(V1.1起)

使用顶点数组对几何图形进行渲染需要三个步骤:
a. 激活最多8个数组,每个数组用于存储不同类型的数据:顶点坐标、表面法线、RGBA颜色、辅助颜色、颜色索引、雾坐标、纹理坐标以及多边形的边界标志。
    glEnableClientState(GLenum array)
    glDisableClientState(GLenum array)

        array可取的值有: GL_VERTEX_ARRAY  GL_COLOR_ARRAY  GL_SECONDRY_COLOR_ARRAY  GL_INDEX_ARRAY  GL_NORMAL_ARRAY  GL_FOG_COORDINATE_ARRAY  GL_TEXTURE_COORD_ARRAY  GL_EDGE_FLAG_ARRAY


b. 把数据放入数组中
    glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
    glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
    glSecondaryColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
    glIndexPointer(GLenum type, GLsizei stride, const GLvoid *pointer);
    glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer);
    glFogCoordPointer(GLenum type, GLsizei stride, const GLvoid *pointer);
    glTexCoordPointer(GLenum type, GLsizei stride, const GLvoid *pointer);

    glEdgeFlagPointer(GLsizei stride, const GLvoid *pointer);


c. 用这些数据绘制图形
    glArrayElement(GLint ith)
    当调用glArrayElement时,涉及到的数组发生了数据改变,不能确定渲染时,使用的是改变前的数据还是改变后的数据
    还可以使用: glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
        等价于:
             glBegin(mode);
                for(i = 0; i < count; ++i)
                    glArrayElement(indices[i]);
            glEnd();

    自V1.4, 引入了glMultiDrawElements(GLenum mode, GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount);
    它等价于:
        for(i = 0; i < primcount; ++i){
            if(count[i] > 0)
                glDrawElements(mode, count[i], type, indices[i]);
        }

    其他: glDrawRangeElements、glDrawwArrays



二、缓冲区对象

使应用程序可以显示的指定把哪些数据存储在服务端(即:显卡内存)
  •  从V1.5开始,数组中的顶点数据可以存储在服务器端缓冲区对象中
  •  在V2.1中,加入了在缓冲区对象中存储像素数据(如:纹理贴图或像素块)的支持
  •  V3.1增加了统一缓冲对象以存储成块的、用于着色器的统一变量数据

a. 创建缓冲区对象
    void glGenBuffers(GLsizei n, GLuint *buffers);

    GLboolean glIsBuffer(GLuint buffer);


b. 激活缓冲区对象

    glBindBuffer(GLenum target, GLuint buffer);


c. 用数据分配和初始化缓冲区对象

    glBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);


d. 更新缓冲区对象的数值
    方法一: void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid *data);
    方法二: GLvoid *glMapBuffer(GLenum target, GLenum access); 提供了对缓冲区对象中包含的整个数据集合的访问,如果需要修改缓冲区中的大部分数据,这种方法很有用,但是,如果有一个很大的缓冲区并且只需更新很小的一部分值,这种方法效率很低(因为需要把显卡内存映射到内存中,其消耗性能的性能与其带来的便利不能忽略不计)。
        在完成对数据的访问后,调用GLboolean glUnmapBuffer(GLenum target)取消这个缓冲区的映射。

        其他: glMapBufferRange、 glFlushMappedBufferRange


e. 在缓冲区对象之间复制数据

    glCopyBufferSubData(GLenum readbuffer, GLenum writebuffer, GLintptr readoffset, GLintptr writeoffset, GLsizeiptr size);


f. 清除缓冲区对象

    glDeleteBuffers(GLsizei n, const GLuint *buffer);


3、顶点数组对象

    为了减少类似于glVertexPointer这样的函数的调用,可以使用定点数组对象,它绑定了调用的集合,以设置顶点数组的状态。
    void glGenVertexArrays(GLsizei n, GLuint *arrays);
    void glBindVertexArray(GLuint array);
    void glDeleteVertexArrays(GLsizei n, GLuint *arrays);
    GLboolean glIsVertexArray(GLuint array);

GLuint va[1] = {0};void init(){glGenVertexArrays(1, va);GLfloat trianVerts[][3] = {0.0, 0.0, 0.0,1.0, 1.0, 1.0,0.0, 0.0, 1.0};GLubyte trianIndices[] = {0, 1, 2};glBindVertexArray(va[0]);glVertexPointer(3, GL_FLOAT,...);glEnableClientState(GL_VERTEX_ARRAY);}void display(){glBindVertexArray(va[0]);glDrawElements(GL_TRIANGLES, 1...);        ...}