【问题标题】:OpenGL glMultiDrawElementsIndirect with Interleaved Buffers带有交错缓冲区的 OpenGL glMultiDrawElementsIndirect
【发布时间】:2015-12-16 01:14:35
【问题描述】:

最初使用glDrawElementsInstancedBaseVertex 来绘制场景网格。所有网格顶点属性都在单个缓冲区对象中交错。总共只有 30 个独特的网格。所以我一直用实例计数等调用draw 30 次,但现在我想使用glMultiDrawElementsIndirect 将draw 调用批处理为一个。由于我没有使用此命令功能的经验,因此我一直在到处阅读文章以了解实现,但收效甚微。 (出于测试目的,所有网格都只实例化一次)。

OpenGL 参考页中的命令结构。

struct DrawElementsIndirectCommand
{
    GLuint vertexCount;
    GLuint instanceCount;
    GLuint firstVertex;
    GLuint baseVertex;
    GLuint baseInstance;
};

DrawElementsIndirectCommand commands[30];

// Populate commands.
for (size_t index { 0 }; index < 30; ++index)
{
    const Mesh* mesh{ m_meshes[index] };

    commands[index].vertexCount     = mesh->elementCount;
    commands[index].instanceCount   = 1; // Just testing with 1 instance, ATM.
    commands[index].firstVertex     = mesh->elementOffset();
    commands[index].baseVertex      = mesh->verticeIndex();
    commands[index].baseInstance    = 0; // Shouldn't impact testing?
}
// Create and populate the GL_DRAW_INDIRECT_BUFFER buffer... bla bla

然后下线,设置完成后我会画一些图。

// Some prep before drawing like bind VAO, update buffers, etc.
// Draw?
if (RenderMode == MULTIDRAW)
{
    // Bind, Draw, Unbind
    glBindBuffer(GL_DRAW_INDIRECT_BUFFER, m_indirectBuffer);
    glMultiDrawElementsIndirect (GL_TRIANGLES, GL_UNSIGNED_INT, nullptr, 30, 0);
    glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0);
}
else
{
    for (size_t index { 0 }; index < 30; ++index)
    {
        const Mesh* mesh { m_meshes[index] };

        glDrawElementsInstancedBaseVertex(
            GL_TRIANGLES,
            mesh->elementCount,
            GL_UNSIGNED_INT,
            reinterpret_cast<GLvoid*>(mesh->elementOffset()),
            1,
            mesh->verticeIndex());
    }
}

现在glDrawElements... 在切换时仍然可以像以前一样正常工作。但是尝试glMultiDraw... 会给出无法区分的网格,但是当我将所有命令的firstVertex 设置为0 时,网格看起来几乎是正确的(至少可以区分),但在某些地方仍然很大程度上是错误的?我觉得我遗漏了有关间接多重绘图的重要内容?

【问题讨论】:

    标签: c++ opengl opengl-4


    【解决方案1】:
    //Indirect data
    commands[index].firstVertex     = mesh->elementOffset();
    
    //Direct draw call
    reinterpret_cast<GLvoid*>(mesh->elementOffset()),
    

    这不是间接渲染的工作方式。 firstVertex 不是字节偏移;它是第一个顶点索引。所以你必须将字节偏移量除以索引的大小来计算firstVertex

    commands[index].firstVertex     = mesh->elementOffset() / sizeof(GLuint);
    

    结果应该是一个整数。如果不是,那么您正在执行未对齐的读取,这可能会损害您的性能。所以修复它;)

    【讨论】:

      猜你喜欢
      • 2011-12-30
      • 1970-01-01
      • 2014-06-26
      • 1970-01-01
      • 1970-01-01
      • 2018-04-21
      • 2016-01-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多