OpenGL 3.3 Core-Profile:如何管理缓冲区数组以绘制多个基元?

时间:2018-07-13 07:46:39

标签: opengl buffer draw

我正在按照this教程编写OpenGL应用程序。我有一个3D对象的数据集,其中每个对象的描述如下:

  • 位置(3D矢量)
  • 边界框(上下3D矢量)
  • 点云(在我的情况下是pcd文件)

到目前为止,我设法绘制了从pcd文件加载的点云(here,您可以找到代码)。在渲染循环中,我写道:

  //3) bind VAO
  glBindVertexArray(_VAO);

  //4) draw
  glDrawArrays(GL_POINTS,0,_num_vertices);

我在GL_BUFFER_ARRAY中存储了云的顶点。

现在,我的问题是:

对于此对象,我还想绘制一个边界框(作为线框矩形)和一组以其位置为中心的3d轴(作为一组三个圆柱)。最好的方法是什么?


@MichaelIV

感谢您的回复。我正在听取您的建议,但是我的行为很奇怪。

要填充缓冲区,我编写了以下代码:

  Eigen::Vector3f min(1.7921,-0.2782,0.0);
  Eigen::Vector3f max(2.1521,0.1994,0.9915);

  insertVertex(_box_vertices,min.x(),min.y(),min.z(),0.0,0.0,1.0);
  insertVertex(_box_vertices,max.x(),min.y(),min.z(),0.0,0.0,1.0);
  insertVertex(_box_vertices,max.x(),max.y(),min.z(),0.0,0.0,1.0);
  insertVertex(_box_vertices,min.x(),max.y(),min.z(),0.0,0.0,1.0);

  _num_box_vertices = _box_vertices.size()/6.0f;
  std::cerr << "Box vertices:" << std::endl;
  for(size_t i=0; i<_num_box_vertices; ++i){
    std::cerr << _box_vertices[6*i] << " " << _box_vertices[6*i+1] << " " << _box_vertices[6*i+2] << " ";
    std::cerr << _box_vertices[6*i+3] << " " << _box_vertices[6*i+4] << " " << _box_vertices[6*i+5] << std::endl;
  }

其中_box_vertices是一个std::vector<float>数组,而insertVertex只是一个实用函数。如果我打印数组,这就是我得到的:

dede@srrg-02:~/source/develop/opengl_viewer/bin$ ./opengl_viewer
Box vertices:
1.7921 -0.2782 0 0 0 1
2.1521 -0.2782 0 0 0 1
2.1521 0.1994 0 0 0 1
1.7921 0.1994 0 0 0 1

因此,它应该是正确的。然后,我使用以下代码(OpenGL 3.3)分配gl对象:

  //[OPENGL] create box buffers
  glGenBuffers(1, &_bVBO);
  glBindBuffer(GL_ARRAY_BUFFER, _bVBO);
  glBufferData(GL_ARRAY_BUFFER, _box_vertices.size()*sizeof(float), &_box_vertices[0], GL_STATIC_DRAW);

  glGenVertexArrays(1, &_bVAO);
  glBindVertexArray(_bVAO);

  //[OPENGL] link box vertex attributes
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3* sizeof(float)));
  glEnableVertexAttribArray(1);

并以此呈现它们:

  //3) bind box VAO
  glBindVertexArray(_bVAO);

  //4) draw box
  glDrawArrays(GL_LINE_LOOP,0,_num_box_vertices);

但是结果却不是我所期望的:

enter image description here

似乎每一行都从(0,0,0)开始,而不是从我想要的点开始。

能否请您解释一下该如何解决?

谢谢。

1 个答案:

答案 0 :(得分:0)

这是我如何绘制边界(GL 4.5 API):

初始化一次:

         Gluint mVao = 0;
          //CReate VAO:
         glCreateVertexArrays(1, &mVao);

         glEnableVertexArrayAttrib(mVao, 0);
         glVertexArrayAttribFormat(mVao, 0, 3, GL_FLOAT, GL_FALSE, 0);
         //Create VBO
         glCreateBuffers(1,&mVbo);
         glNamedBufferData(mVbo, dataSize, NULL, GL_DYNAMIC_DRAW);
         //Bind VBO to VAO
         glVertexArrayAttribBinding(mVao, 0, 0);
         glVertexArrayVertexBuffer(mVao, 0, mVbo, 0, sizeof(float) * 3);

在每一帧上:

准备AABB顶点(使用GLM数学库),aabb可能是一些DrawDebug()函数参数:

        const GLfloat data[48] = {
        // Loop 1: XY Z (min)
        aabb.mMin.x, aabb.mMin.y, aabb.mMin.z,
        aabb.mMax.x, aabb.mMin.y, aabb.mMin.z,
        aabb.mMax.x, aabb.mMax.y, aabb.mMin.z,
        aabb.mMin.x, aabb.mMax.y, aabb.mMin.z,

        // Loop 2: XY Z (max)
        aabb.mMin.x, aabb.mMin.y, aabb.mMax.z,
        aabb.mMax.x, aabb.mMin.y, aabb.mMax.z,
        aabb.mMax.x, aabb.mMax.y, aabb.mMax.z,
        aabb.mMin.x, aabb.mMax.y, aabb.mMax.z,

        // Lists:
        // 1
        aabb.mMin.x, aabb.mMin.y, aabb.mMin.z,
        aabb.mMin.x, aabb.mMin.y, aabb.mMax.z,
        // 2
        aabb.mMax.x, aabb.mMin.y, aabb.mMin.z,
        aabb.mMax.x, aabb.mMin.y, aabb.mMax.z,
        // 3
        aabb.mMax.x, aabb.mMax.y, aabb.mMin.z,
        aabb.mMax.x, aabb.mMax.y, aabb.mMax.z,
        // 4
        aabb.mMin.x, aabb.mMax.y, aabb.mMin.z,
        aabb.mMin.x, aabb.mMax.y, aabb.mMax.z,
    };

    glNamedBufferSubData(mVbo,0, mDataSize, data);

   //combine line loop and line drawing to minimize number of draw calls:
    glDrawArrays(GL_LINE_LOOP, 0, 4);
    glDrawArrays(GL_LINE_LOOP, 4, 4);
    glDrawArrays(GL_LINES, 8, 8));

重要注意:我在这里省略了着色器程序绑定,因为那里没有什么特别的。但是您必须提供着色器程序,其中顶点着色器使用MVP对aabb坐标进行转换(模型-视图-投影)矩阵,或者如果您在客户端使用模型矩阵转换了aabb顶点,则仅使用视图-投影矩阵。