【问题标题】:Using glDrawElements with multiple meshes将 glDrawElements 与多个网格一起使用
【发布时间】:2015-07-27 18:42:22
【问题描述】:

我可以使用 glDrawArrays 成功绘制一个如下所示的场景:

这种技术有点慢,所以我决定制作一个 indexbuffer 并尝试使用 glDrawElements。结果如下所示:

如您所见,右上角的方块渲染不正确,飞机下方的方块消失了。

生成缓冲区的代码

//create vertex and index buffer 
glGenBuffers(1, &gVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, gVertexBuffer);   
glGenBuffers(1, &gIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIndexBuffer);

// Define the size of the buffers   
GLuint floatAmount = 0;
GLuint GLuintAmount = 0;
for each (MeshObject* mesh in meshes)
{
    floatAmount += mesh->GetFloatAmount();
    GLuintAmount += mesh->GetGLuintAmount();
}
glBufferData(GL_ARRAY_BUFFER, floatAmount, 0, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, GLuintAmount, 0, GL_STATIC_DRAW);


// Define size and offset of the different subdata in the buffers
GLuint offsetVer = 0;
GLuint offsetInd = 0;
for each (MeshObject* mesh in meshes)
{
    // Set offset for mesh
    mesh->SetOffset(offsetVer / sizeof(Point));
    mesh->SetOffsetInd(offsetInd);

    glBufferSubData(GL_ARRAY_BUFFER,
        offsetVer,
        mesh->GetFloatAmount(),
        mesh->GetPoints().data());

    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER,
        offsetInd,
        mesh->GetGLuintAmount(),
        mesh->GetIndicies().data());

    offsetVer += mesh->GetFloatAmount();
    offsetInd += mesh->GetGLuintAmount();
}

...以及渲染代码

glBindBuffer(GL_ARRAY_BUFFER, gVertexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gIndexBuffer);

mat4 vwMatrix = localCamera->GetPVMatrix() * mh->GetWorld();

glUniformMatrix4fv(projectionviewworldMatrixUniformLocation, 1, GL_FALSE, &(GLfloat)vwMatrix[0][0]);

//glDrawArrays(GL_TRIANGLES, mh->mesh->GetOffset(), mh->mesh->GetPoints().size());
glDrawElements(GL_TRIANGLES, mh->mesh->GetIndicies().size(), GL_UNSIGNED_INT, (void*)mh->mesh->GetOffsetInd());

//GLuint size = mh->mesh->GetIndicies().size();
//GLuint IndSize = mh->mesh->GetOffsetInd();
//glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, (void*)IndSize);

【问题讨论】:

  • mesh->SetOffset(offsetVer / sizeof(Point)); mesh->SetOffsetInd(offsetInd); 是做什么的?
  • 第一个offsetVer,不是用于glDrawElements,而是用于glDrawArrays。它是一个偏移量,可以按预期工作,但在这种情况下可能没用。第二个,offsetInd,是我想为 glDrawElements 中的最后一个参数设置的偏移量,但我不知道这是否是正确的方法。

标签: opengl graphics 3d rendering


【解决方案1】:

您需要在索引缓冲区的每个元素上添加offsetVer。这是一个例子:

网格 A(1 个三角形)

Vertices: v0 v1 v2
Indices: 0 1 2

网格 B(1 个三角形)

Vertices: v3 v4 v5
Indices: 0 1 2

这就是你的组合缓冲区的样子:

Vertices: v0 v1 v2 v3 v4 v5
Indices: 0 1 2 0 1 2

应该是这样的:

Vertices: v0 v1 v2 v3 v4 v5
Indices: 0 1 2 3 4 5

【讨论】:

  • 它解决了我的问题,但是增加了缓冲区的创建速度。 ( for (GLuint i = 0; i GetIndicies().size(); i++) { mesh->indicies[i] += offsetVer / sizeof(Point); } )。您知道执行此操作的更快方法还是无法优化?
  • 如果将除法移出循环,此方法只会为每个索引添加 1 个额外的定点加法。这在现代 CPU 上几乎不会引起注意,因为这样的循环可以很好地优化,考虑到您必须从硬盘驱动器加载网格,这应该会对性能产生更大的影响这一事实可以忽略不计。
  • 我移动了部门,并没有发现真正的区别。不同之处(对于使用 std::vector 的每个人都应该是一个警告)是对函数 size() 的调用。如果我保存变量并避免调用 68500 次(飞机网格的索引计数),则启动或多或少是即时的。我觉得这实际上有点荒谬:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-25
相关资源
最近更新 更多