顶点数组
例如顶点 (x, y, z)、法线 (x, y, z) 和纹理坐标 (u, v) 的缓冲区:
绘制数组:
GLsizei no_of_points; // number of vertices and attrbuts
std::vector<GLfloat> vertex; // linearized array (no_of_points * 3): [ Vx0, Vy0, Vz0, Vx1, Vy1, Vz1, .... ]
std::vector<GLfloat> normal; // linearized array (no_of_points * 3): [ Nx0, Ny0, Nz0, Nx1, Ny1, Nz1, .... ]
std::vector<GLfloat> color; // linearized array (no_of_points * 5): [ R0, G0, B0, A0, R1, G1, B1, A1, .... ]
GLuint vetexAttribIndex; // index of the vertex attrbute (shader)
GLuint normalAttribIndex; // index of the normal attribute (shader)
GLuint colorAttribIndex; // index of the color attribute (shader)
glVertexAttribPointer( vetexAttribIndex, 3, GL_FLOAT, GL_FALSE, 0, vertex.data() ); // 3: Vx, Vy, Vz
glVertexAttribPointer( normalAttribIndex, 3, GL_FLOAT, GL_TRUE, 0, normal.data() ); // 3: Nx, Ny, Nz - GL_TRUE: values should be normalized
glVertexAttribPointer( colorAttribIndex, 4, GL_FLOAT, GL_FALSE, 0, color.data() ); // 4: R, G, B, A
glEnableVertexAttribArray( vetexAttribIndex );
glEnableVertexAttribArray( normalAttribIndex );
glEnableVertexAttribArray( colorAttribIndex );
glDrawArrays( GL_TRIANGLES, 0, no_of_points );
glDisableVertexAttribArray( vetexAttribIndex );
glDisableVertexAttribArray( normalAttribIndex );
glDisableVertexAttribArray( colorAttribIndex );
见:
顶点缓冲对象
关于Vertex Specification 的 Khronos OpenGL wiki 明确表示:
glVertexAttribPointer 函数 state 属性索引从中获取其数组数据。
可以使用glGetVertexAttrib 检索此状态。
关于顶点属性的更多信息可以在第 10.2 章到第 10.6 章的OpenGL 4.6. core specification 中找到。
例如顶点、法线向量和纹理坐标
[ Vx0, Vy0, Vz0, Nx0, Ny0, Nz0, Tv0, Tu0,
Vx1, Vy1, Vz1, Nx1, Ny1, Nz1, Tv1, Tu1,
.....
]
创建顶点数组缓冲区:
GLsizei no_of_points;
std::vector<GLfloat> data; // attribute set: [ Vx0, Vy0, Vz0, Nx0, Ny0, Nz0, Tv0, Tu0, Vx1, Vy1, Vz1, Nx1, Ny1, Nz1, Tv1, Tu1, .... ]
GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.data(), GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
见:
绘制数组:
GLuint vetexAttribIndex; // index of the vertex attrbute (shader)
GLuint normalAttribIndex; // index of the normal attribute (shader)
GLuint texCorAttribIndex; // index of the texture coordinate attribute (shader)
glBindBuffer( GL_ARRAY_BUFFER, vbo );
GLsizei stride = 8 * sizeof(GL_float); // size of one record in bytes: 8 * float [ Vx, Vy, Vz, Nx, Ny, Nz, Tv, Tu]
GLsizei offsV = 0 * sizeof(GL_float); // offset of the vertex inside the reccord
GLsizei offsNV = 3 * sizeof(GL_float); // offset of the normal vector inside the reccord
GLsizei offsTC = 6 * sizeof(GL_float); // offset of the tecture coordinate inside the reccord
glVertexAttribPointer( vetexAttribIndex, 3, GL_FLOAT, GL_FALSE, stride, offsV ); // 3: Vx, Vy, Vz
glVertexAttribPointer( normalAttribIndex, 3, GL_FLOAT, GL_TRUE, stride, offsNV ); // 3: Nx, Ny, Nz - GL_TRUE: values should be normalized
glVertexAttribPointer( texCorAttribIndex, 2, GL_FLOAT, GL_FALSE, stride, offsTC ); // 2: Tu, Tv
glEnableVertexAttribArray( vetexAttribIndex );
glEnableVertexAttribArray( normalAttribIndex );
glEnableVertexAttribArray( texCorAttribIndex );
glDrawArrays( GL_TRIANGLES, 0, no_of_points );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glDisableVertexAttribArray( vetexAttribIndex );
glDisableVertexAttribArray( normalAttribIndex );
glDisableVertexAttribArray( texCorAttribIndex );
索引缓冲区对象
例如顶点、法线向量和纹理坐标
[ Vx0, Vy0, Vz0, Nx0, Ny0, Nz0, Tv0, Tu0,
Vx1, Vy1, Vz1, Nx1, Ny1, Nz1, Tv1, Tu1,
.....
]
创建顶点数组缓冲区和索引缓冲区:
GLsizei no_of_points;
std::vector<GLfloat> data; // attribute set: [ Vx0, Vy0, Vz0, Nx0, Ny0, Nz0, Tv0, Tu0, Vx1, Vy1, Vz1, Nx1, Ny1, Nz1, Tv1, Tu1, .... ]
std::vector<GLuint> indices; // indces: [ I0, I1, I2, I3, I4, ..... ]
GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.data(), GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
GLuint ibo;
glGenBuffers( 1, &ibo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
绘制数组:
GLuint vetexAttribIndex; // index of the vertex attrbute (shader)
GLuint normalAttribIndex; // index of the normal attribute (shader)
GLuint texCorAttribIndex; // index of the texture coordinate attribute (shader)
glBindBuffer( GL_ARRAY_BUFFER, vbo );
GLsizei stride = 8 * sizeof(GL_float); // size of one record in bytes: 8 * float [ Vx, Vy, Vz, Nx, Ny, Nz, Tv, Tu]
GLsizei offsV = 0 * sizeof(GL_float); // offset of the vertex inside the reccord
GLsizei offsNV = 3 * sizeof(GL_float); // offset of the normal vector inside the reccord
GLsizei offsTC = 6 * sizeof(GL_float); // offset of the tecture coordinate inside the reccord
glVertexAttribPointer( vetexAttribIndex, 3, GL_FLOAT, GL_FALSE, stride, offsV ); // 3: Vx, Vy, Vz
glVertexAttribPointer( normalAttribIndex, 3, GL_FLOAT, GL_TRUE, stride, offsNV ); // 3: Nx, Ny, Nz - GL_TRUE: values should be normalized
glVertexAttribPointer( texCorAttribIndex, 2, GL_FLOAT, GL_FALSE, stride, offsTC ); // 2: Tu, Tv
glEnableVertexAttribArray( vetexAttribIndex );
glEnableVertexAttribArray( normalAttribIndex );
glEnableVertexAttribArray( texCorAttribIndex );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glDrawElements( GL_TRIANGLES, (GLsizei)indices.size(), GL_UNSIGNED_INT, nullptr );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
glDisableVertexAttribArray( vetexAttribIndex );
glDisableVertexAttribArray( normalAttribIndex );
glDisableVertexAttribArray( texCorAttribIndex );
顶点数组对象
要处理不同的顶点属性指针而不是交替指定和启用或禁用它们,可以生成一个顶点数组对象(glGenVertexArrays,它存储了有关缓冲区位置、数据格式、状态和属性索引的所有信息:
见OpenGL 4.6 core Specification - 10.3.1 Vertex Array Objects:
将GL的顶点阶段要使用的缓冲区对象收集在一起,形成一个顶点数组对象。
所有与顶点处理器使用的数据定义相关的状态都封装在一个顶点数组对象中。
....
当前绑定的顶点数组对象用于所有修改顶点数组状态的命令,例如VertexAttribPointer和EnableVertexAttribArray;
所有从顶点数组中绘制的命令,例如 DrawArrays 和 DrawElements;
例如顶点、法线向量和纹理坐标
[ Vx0, Vy0, Vz0, Nx0, Ny0, Nz0, Tv0, Tu0,
Vx1, Vy1, Vz1, Nx1, Ny1, Nz1, Tv1, Tu1,
.....
]
创建顶点数组缓冲区和索引缓冲区:
GLsizei no_of_points;
std::vector<GLfloat> data; // attribute set: [ Vx0, Vy0, Vz0, Nx0, Ny0, Nz0, Tv0, Tu0, Vx1, Vy1, Vz1, Nx1, Ny1, Nz1, Tv1, Tu1, .... ]
std::vector<GLuint> indices; // indces: [ I0, I1, I2, I3, I4, ..... ]
GLuint vbo;
glGenBuffers( 1, &vbo );
glBindBuffer( GL_ARRAY_BUFFER, vbo );
glBufferData( GL_ARRAY_BUFFER, data.size() * sizeof(GLfloat), data.data(), GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER, 0 );
GLuint ibo;
glGenBuffers( 1, &ibo );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo );
glBufferData( GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLuint), indices.data(), GL_STATIC_DRAW );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 );
创建顶点数组对象:
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );
GLuint vetexAttribIndex; // index of the vertex attrbute (shader)
GLuint normalAttribIndex; // index of the normal attribute (shader)
GLuint texCorAttribIndex; // index of the texture coordinate attribute (shader)
glBindBuffer( GL_ARRAY_BUFFER, vbo );
GLsizei stride = 8 * sizeof(GL_float); // size of one record in bytes: 8 * float [ Vx, Vy, Vz, Nx, Ny, Nz, Tv, Tu]
GLsizei offsV = 0 * sizeof(GL_float); // offset of the vertex inside the reccord
GLsizei offsNV = 3 * sizeof(GL_float); // offset of the normal vector inside the reccord
GLsizei offsTC = 6 * sizeof(GL_float); // offset of the tecture coordinate inside the reccord
glVertexAttribPointer( vetexAttribIndex, 3, GL_FLOAT, GL_FALSE, stride, offsV ); // 3: Vx, Vy, Vz
glVertexAttribPointer( normalAttribIndex, 3, GL_FLOAT, GL_TRUE, stride, offsNV ); // 3: Nx, Ny, Nz - GL_TRUE: values should be normalized
glVertexAttribPointer( texCorAttribIndex, 2, GL_FLOAT, GL_FALSE, stride, offsTC ); // 2: Tu, Tv
glEnableVertexAttribArray( vetexAttribIndex );
glEnableVertexAttribArray( normalAttribIndex );
glEnableVertexAttribArray( texCorAttribIndex );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, ibo ); // Associate the element array buffer (index buffer) to the vertex array object
glBindVertexArray( 0 ); // Unbind the vertex array object
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); // Unbinde the element array buffer. This has to be done after the vertex array object is unbound, otherwise the association to the vertex array object would be lost.
见:
绘制数组:
glBindVertexArray( vao );
glDrawElements( GL_TRIANGLES, (GLsizei)indices.size(), GL_UNSIGNED_INT, nullptr );
glBindVertexArray( 0 );
注意,与index buffer (ELEMENT_ARRAY_BUFFER) 相比,vertex buffer 绑定 (ARRAY_BUFFER) 是一个全局状态。
在 VAO 状态向量中陈述的每个属性都可以引用不同的ARRAY_BUFFER。在调用glVertexAttribPointer 时存储此引用,然后将当前绑定到目标ARRAY_BUFFER 的缓冲区关联到指定的属性索引,并将对象的名称(值)存储在当前的状态向量中绑定 VAO。
但索引缓冲区是 VAO 的一种状态。当缓冲区绑定到目标ELEMENT_ARRAY_BUFFER 时,此缓冲区将关联到当前绑定的顶点数组对象。