分批顶点
通常我们使用交错布局处理顶点数据,与交错布局123123123123不同,我们也可以采用分批(Batched)的方式111122223333。
我们可以先用glBufferData函数预留一块内存,如果我们将它的data参数设置为NULL,那么这个函数将只会分配内存,但不进行填充。
然后使用glBufferSubData函数填充缓存。一个缓冲目标、一个偏移量、数据的大小和数据本身作为它的参数。
要注意的是,缓冲需要有足够的已分配内存,所以对一个缓冲调用glBufferSubData之前必须要先调用glBufferData。
glBufferSubData(GL_ARRAY_BUFFER, 24, sizeof(data), &data);
通过这个函数,就可以将整批顶点属性填充。
float positions[] = { ... };
float normals[] = { ... };
float tex[] = { ... };
// 填充缓冲
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), &positions);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions), sizeof(normals), &normals);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions) + sizeof(normals), sizeof(tex), &tex);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(sizeof(positions)));
glVertexAttribPointer(
2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)(sizeof(positions) + sizeof(normals)));
注意,步长的含义是两个连续顶点属性之间的距离。这样写实际上顶点位置的VAO也错误地包含了后面法线和纹理的数据,但是因为我们没有调用后面错误的部分,所以不影响使用。
复制缓冲
glCopyBufferSubData能够让我们相对容易地从一个缓冲中复制数据到另一个缓冲中。
以下是函数原型:
void glCopyBufferSubData(GLenum readtarget, GLenum writetarget, GLintptr readoffset,
GLintptr writeoffset, GLsizeiptr size);
float vertexData[] = { ... };
glBindBuffer(GL_COPY_READ_BUFFER, vbo1);
glBindBuffer(GL_COPY_WRITE_BUFFER, vbo2);
glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, sizeof(vertexData));