带交错缓冲区的 OpenGL glMultiDrawElementsIndirect
OpenGL glMultiDrawElementsIndirect with Interleaved Buffers
最初使用glDrawElementsInstancedBaseVertex
绘制场景网格。所有网格顶点属性都交错在单个缓冲区对象中。总共只有 30 个独特的网格。所以我一直在使用实例计数等调用绘制 30 次,但现在我想使用 glMultiDrawElementsIndirect
将绘制调用批量化为一个。由于我没有使用过此命令功能的经验,因此我一直在各处阅读文章以了解其实现,但收效甚微。 (出于测试目的,所有网格仅实例化一次)。
来自 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
时,网格看起来几乎是正确的(至少可以区分)但在某些地方仍然有很大的错误?我觉得我遗漏了一些关于间接多重绘图的重要信息?
//Indirect data
commands[index].firstVertex = mesh->elementOffset();
//Direct draw call
reinterpret_cast<GLvoid*>(mesh->elementOffset()),
这不是间接渲染的工作方式。 firstVertex
不是字节偏移;这是 第一个顶点 索引。所以你必须将字节偏移量除以索引的大小来计算 firstVertex
:
commands[index].firstVertex = mesh->elementOffset() / sizeof(GLuint);
其结果应该是一个整数。如果不是,那么您正在进行未对齐的读取,这可能会损害您的性能。所以解决这个问题 ;)
最初使用glDrawElementsInstancedBaseVertex
绘制场景网格。所有网格顶点属性都交错在单个缓冲区对象中。总共只有 30 个独特的网格。所以我一直在使用实例计数等调用绘制 30 次,但现在我想使用 glMultiDrawElementsIndirect
将绘制调用批量化为一个。由于我没有使用过此命令功能的经验,因此我一直在各处阅读文章以了解其实现,但收效甚微。 (出于测试目的,所有网格仅实例化一次)。
来自 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
时,网格看起来几乎是正确的(至少可以区分)但在某些地方仍然有很大的错误?我觉得我遗漏了一些关于间接多重绘图的重要信息?
//Indirect data
commands[index].firstVertex = mesh->elementOffset();
//Direct draw call
reinterpret_cast<GLvoid*>(mesh->elementOffset()),
这不是间接渲染的工作方式。 firstVertex
不是字节偏移;这是 第一个顶点 索引。所以你必须将字节偏移量除以索引的大小来计算 firstVertex
:
commands[index].firstVertex = mesh->elementOffset() / sizeof(GLuint);
其结果应该是一个整数。如果不是,那么您正在进行未对齐的读取,这可能会损害您的性能。所以解决这个问题 ;)