因为有需要对网格顶点属性实时更新,所以我之前使用的 API 是:glBufferData
// method 1:
glBindBuffer(GL_ARRAY_BUFFER, vbos[(int)MeshVboType::POSITION]);
glBufferData(GL_ARRAY_BUFFER, arr->bytes_size(), arr->ptr(), _dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
checkGLError();
但是从 API 参数可以看到,它需要获取 GL_ARRAY_BUFFER 类型缓存的指针,指定分配大小,并设置数据,并指定缓存区块是类型。
对于我们只需要更新数据来说,这个 API 做的东西过多了。
然后,我在继续学习 LearnGL 系列的过程中,法线另一对 API: glMapBuffer、glUnmapBuffer,这对 API 正式我需要的功能,我的学习项目中的代码如下:
void Mesh::uploadPos(FixedArray<GLfloat>* arr) {
if (!_uploaded) return;
if (arr != _vertices) {
assert(arr != NULL);
DESTROY(_vertices);
_vertices = arr;
pos_copy_from(arr->ptrType(), arr->size());
// 新的缓存
// vbo
glBindBuffer(GL_ARRAY_BUFFER, vbos[(int)MeshVboType::POSITION]);
// pos
glBufferData(GL_ARRAY_BUFFER, _vertices->bytes_size(), _vertices->ptr(), _dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
glVertexAttribPointer(pos_loc, 3, GL_FLOAT, GL_FALSE, 0, (GLvoid*)0);
glEnableVertexAttribArray(pos_loc);
_vertices_byte_size = _vertices->bytes_size();
_vertices_count = _vertices->size() / 3;
checkGLError();
}
else {
// method 1:
//glBindBuffer(GL_ARRAY_BUFFER, vbos[(int)MeshVboType::POSITION]);
//glBufferData(GL_ARRAY_BUFFER, arr->bytes_size(), arr->ptr(), _dynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
//checkGLError();
// method 2:
// 参考:https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/07%20Advanced%20Data/
// 设置当前 VB O对象
glBindBuffer(GL_ARRAY_BUFFER, vbos[(int)MeshVboType::POSITION]);
// 获取当前 VBO 的只写指针
void* ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
// 复制数据到内存
memcpy(ptr, arr->ptr(), arr->bytes_size());
// 记得告诉OpenGL我们不再需要这个指针了
if (glUnmapBuffer(GL_ARRAY_BUFFER) != GL_TRUE) {
std::cerr << "Mesh Update Pos Failure!\n";
}
checkGLError();
}
}
结合上下文,主要看下部的部分:
// 参考:https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/07%20Advanced%20Data/
// 设置当前 VB O对象
glBindBuffer(GL_ARRAY_BUFFER, vbos[(int)MeshVboType::POSITION]);
// 获取当前 VBO 的只写指针
void* ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
// 复制数据到内存
memcpy(ptr, arr->ptr(), arr->bytes_size());
// 记得告诉OpenGL我们不再需要这个指针了
if (glUnmapBuffer(GL_ARRAY_BUFFER) != GL_TRUE) {
std::cerr << "Mesh Update Pos Failure!\n";
}
这样我们仅仅做的是:获取 GL_ARRAY_BUFFER
缓存的 只写 指定,然后对该指针的数据更新,在告诉 OpenGL 关闭该 只写指针,非常适合我的需求。