【问题标题】:OpenGL 3.3 Core-Profile: How to manage buffer arrays to draw several primitives?OpenGL 3.3 Core-Profile:如何管理缓冲区数组以绘制多个图元?
【发布时间】:2018-07-13 07:46:39
【问题描述】:

我正在关注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_verticesstd::vector&lt;float&gt; 数组,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);

但结果不是我所期望的:

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

你能解释一下如何解决这个问题吗?

谢谢。

【问题讨论】:

  • 参见 complete GL+GLSL+VAO/VBO C++ example 并查看立方体的 VAO/VBO 示例。您的 bbox 将具有几乎相同的点(使用最小值、最大值而不是 +/-1.0)但不同的原始值 (GL_LINES) 和略有不同的索引。但是在旧式 api 中做 bbox 更容易(在核心配置文件中不可行)...
  • 您应该将线的开始/结束位置放入缓冲区中,并与其他几何体做同样的事情,但使用 GL_LINES 或 LINE_STRIP 模式。

标签: opengl buffer draw


【解决方案1】:

这是我绘制边界的方式(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 顶点,则仅使用视图 - 投影矩阵。

【讨论】:

    猜你喜欢
    • 2011-11-24
    • 1970-01-01
    • 2014-01-16
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-24
    • 1970-01-01
    相关资源
    最近更新 更多