[英]OpenGL VBO Safe Practices In A Dynamic Environment (Specific Use Case)
根据http://www.opengl.org/wiki/Vertex_Specification_Best_Practices ,在动态VBO部分下,如果场景频繁更改,建议您将VBO类型设置为GL_DYNAMIC_DRAW。 此外,如果必须更新整个缓冲区,则不要单独使用glBufferSubData。 而是使用glBufferData,然后可以将其数据指针设置为NULL,然后调用glBufferSubData将数据加载到VBO中。
我正在编写的一个Qt程序中正是这样做,它允许用户调整OpenGL可绘制区域(QGLWidget)的大小,根据是否显示更多或更少的数据,强制重绘一组行(一组线框)在给定的QGLWidget中。 我有一个初始的工作示例,它在第一次初始调整大小后工作。 该计划看起来像:
现在,当我第二次调整大小时,应用程序看起来像:
我已经缩小了问题,重新加载与线路相关的VBO。 加载与行关联的顶点属性的代码是:
bool batch_renderer::load_data(render_data_type &data, GLsizei buffer_count)
{
if (_vbo_id) {
glBindBuffer(GL_ARRAY_BUFFER, _vbo_id);
glDeleteBuffers(_byte_count, &_vbo_id);
_vbo_id = 0;
_vertex_count = 0;
_byte_count = 0;
_byte_count1 = 0;
_byte_count2 = 0;
_byte_count3 = 0;
_byte_count4 = 0;
}
_vertex_count = data._data_1.size();
_byte_count = data.size_of();
glGenBuffers(buffer_count, &_vbo_id);
if (bind()) {
glBufferData(GL_ARRAY_BUFFER, _byte_count, NULL, GL_DYNAMIC_DRAW);
switch (data._type_count) {
case (4): {
_byte_count4 = data.data4_size_of();
size_t offset = data.t4_offset();
glBufferSubData(GL_ARRAY_BUFFER, offset, _byte_count4,
data._data_4.data());
}
case (3): {
_byte_count3 = data.data3_size_of();
size_t offset = data.t3_offset();
glBufferSubData(GL_ARRAY_BUFFER, offset, _byte_count3,
data._data_3.data());
}
case (2): {
_byte_count2 = data.data2_size_of();
size_t offset = data.t2_offset();
glBufferSubData(GL_ARRAY_BUFFER, offset, _byte_count2,
data._data_2.data());
}
case (1): {
_byte_count1 = data.data1_size_of();
size_t offset = data.t1_offset();
glBufferSubData(GL_ARRAY_BUFFER, offset, _byte_count1,
data._data_1.data());
}
break;
default: {
return false;
}
}
} else {
return false;
}
return true;
}
如果我注释掉重新加载VBO的源代码,那么在任何调整大小事件之后,程序看起来如下:
我在VBO中做错了什么导致线条出错,而且纹理都搞砸了?
更新整个缓冲区时调用glBufferData
是重用现有的缓冲区对象,告诉驱动程序丢弃旧数据。 这意味着您不必这样做
if (_vbo_id) {
glBindBuffer(GL_ARRAY_BUFFER, _vbo_id);
glDeleteBuffers(_byte_count, &_vbo_id);
_vbo_id = 0;
_vertex_count = 0;
_byte_count = 0;
_byte_count1 = 0;
_byte_count2 = 0;
_byte_count3 = 0;
_byte_count4 = 0;
}
因此,在生成ID之前,只需检查是否未设置
if(!_vbo_id)
glGenBuffers(buffer_count, &_vbo_id);
请注意,我发现总缓冲区对象重新分配与glBufferData
和更新整个事物glBufferSubData
是可以忽略的。 但是你必须描述自己的程序,以做出明智的决定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.