OpenGL glMultiDrawElementsIndirect 与交错缓冲区 [英] OpenGL glMultiDrawElementsIndirect with Interleaved Buffers

查看:118
本文介绍了OpenGL glMultiDrawElementsIndirect 与交错缓冲区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Originally using glDrawElementsInstancedBaseVertex to draw the scene meshes. All the meshes vertex attributes are being interleaved in a single buffer object. In total there are only 30 unique meshes. So I've been calling draw 30 times with instance counts, etc. but now I want to batch the draw calls into one using glMultiDrawElementsIndirect. Since I have no experience with this command function, I've been reading articles here and there to understand the implementation with little success. (For testing purposes all meshes are instanced only once).

来自 OpenGL 参考页面的命令结构.

The command structure from the OpenGL reference page.

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

然后下线,设置后我画了一些图.

Then later down the line, after setup I do some drawing.

// 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 时,网格看起来几乎是正确的(至少可区分)但在某些地方仍然是错误的??我觉得我遗漏了一些关于间接多重绘图的重要内容?

Now the glDrawElements... still works fine like before when switched. But trying glMultiDraw... gives indistinguishable meshes but when I set the firstVertex to 0 for all commands, the meshes look almost correct (at least distinguishable) but still largely wrong in places?? I feel I'm missing something important about indirect multi-drawing?

推荐答案

//Indirect data
commands[index].firstVertex     = mesh->elementOffset();

//Direct draw call
reinterpret_cast<GLvoid*>(mesh->elementOffset()),

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

That's not how it works for indirect rendering. The firstVertex is not a byte offset; it's the first vertex index. So you have to divide the byte offset by the size of the index to compute firstVertex:

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

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

The result of that should be a whole number. If it wasn't, then you were doing unaligned reads, which probably hurt your performance. So fix that ;)

这篇关于OpenGL glMultiDrawElementsIndirect 与交错缓冲区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆