简体   繁体   English

动态环境中的OpenGL VBO安全实践(特定用例)

[英]OpenGL VBO Safe Practices In A Dynamic Environment (Specific Use Case)

According to http://www.opengl.org/wiki/Vertex_Specification_Best_Practices , Under the dynamic VBO section, it is recommended that you set the VBO type to GL_DYNAMIC_DRAW if your scene changes frequently. 根据http://www.opengl.org/wiki/Vertex_Specification_Best_Practices ,在动态VBO部分下,如果场景频繁更改,建议您将VBO类型设置为GL_DYNAMIC_DRAW。 In addition, if you have to update the entire buffer you don't use glBufferSubData alone. 此外,如果必须更新整个缓冲区,则不要单独使用glBufferSubData。 Instead you use glBufferData, and then you can set its data pointer to NULL followed by calls to glBufferSubData to load the data into the VBO. 而是使用glBufferData,然后可以将其数据指针设置为NULL,然后调用glBufferSubData将数据加载到VBO中。

I am doing exactly that in a Qt program I am writing which allows the user to resize the OpenGL drawable area (QGLWidget), which forces a set of lines (a wireframe of sorts) to be redrawn based on if more or less data is displayed in the given QGLWidget. 我正在编写的一个Qt程序中正是这样做,它允许用户调整OpenGL可绘制区域(QGLWidget)的大小,根据是否显示更多或更少的数据,强制重绘一组行(一组线框)在给定的QGLWidget中。 I have an initial working example which works after the first initial resize. 我有一个初始的工作示例,它在第一次初始调整大小后工作。 The program looking like: 该计划看起来像:

Now when I go to resize it a second time the application looks like: 现在,当我第二次调整大小时,应用程序看起来像:

I have narrowed down the problem to re-loading the VBO associated with the lines. 我已经缩小了问题,重新加载与线路相关的VBO。 The code for loading the vertex attributes associated with the lines is: 加载与行关联的顶点属性的代码是:

  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;
  }

If I comment out the source which re-loads the VBO then the progam looks as follows after ANY resize event: 如果我注释掉重新加载VBO的源代码,那么在任何调整大小事件之后,程序看起来如下:

What am I doing wrong here with the VBO to cause the lines to go wrong, and the texture to be all messed up? 我在VBO中做错了什么导致线条出错,而且纹理都搞砸了?

The point of calling glBufferData when updating the whole buffer is to reuse an existing buffer object, telling the driver to discard the old data. 更新整个缓冲区时调用glBufferData是重用现有的缓冲区对象,告诉驱动程序丢弃旧数据。 Which means that you don't have to do this 这意味着您不必这样做

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;
}

So before generating the ID, just check if that's unset 因此,在生成ID之前,只需检查是否未设置

if(!_vbo_id)
    glGenBuffers(buffer_count, &_vbo_id);

Note that I found the difference between total buffer object reallocation with glBufferData and updating the whole thing glBufferSubData to be neglectible. 请注意,我发现总缓冲区对象重新分配与glBufferData和更新整个事物glBufferSubData是可以忽略的。 But you have to profile your own program to make an informed decision. 但是你必须描述自己的程序,以做出明智的决定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM