在给 glMultiDrawElementsIndirect 的命令结构中,firstIndex 参数是什么意思?

What does the firstIndex parameter mean, in the command structure given to glMultiDrawElementsIndirect?

我不明白这个命令结构是如何工作的。除了 firstIndex 之外,所有这些似乎都有意义(在文档中;我实际上还没有调用该函数)。实际上,在我看来好像文档中有错字。

以下是我在查找相关文档时似乎在每个地方都看到的文字:

The parameters addressed by indirect are packed into a structure that takes the form (in C):

typedef  struct {
    uint  count;
    uint  instanceCount;
    uint  firstIndex;
    uint  baseVertex;
    uint  baseInstance;
} DrawElementsIndirectCommand;

A single call to glMultiDrawElementsIndirect is equivalent, assuming no errors are generated to:

GLsizei n;
for (n = 0; n < drawcount; n++) {
    const DrawElementsIndirectCommand *cmd;
    if (stride != 0) {
        cmd = (const DrawElementsIndirectCommand  *)((uintptr)indirect + n * stride);
    } else {
        cmd = (const DrawElementsIndirectCommand  *)indirect + n;
    }

    glDrawElementsInstancedBaseVertexBaseInstance(mode,
                                                  cmd->count,
                                                  type,
                                                  cmd->firstIndex + size-of-type,
                                                  cmd->instanceCount,
                                                  cmd->baseVertex,
                                                  cmd->baseInstance);
}

但是这些页面并没有说明 "size-of-type" 的含义,也没有说明为什么将它添加到 firstIndex,而不是乘以它。看起来 glDrawElementsInstancedBaseVertexBaseInstance 在那里需要一个字节偏移量,所以对我来说 firstIndex 是顶点索引 GL_ELEMENT_ARRAY_BUFFER 数组的索引是有意义的 - 所以,索引的索引 - 以及大小 - -type 是顶点索引(例如 4)的字节大小,您需要在那里将 "index into the indices array" 转换为该数组的字节偏移量。

但是...该转换将表示为乘法,他们说 + 而不是 *。 :(

我说的对吗? firstIndex 是顶点索引数组中条目的索引,size-of-type 是顶点索引的字节大小,+ 是错字吗?如果没有,我错过了什么?

这只是 man page 中的错字。虽然手册页在官方网站上,但它们不是官方文档。它们经常包含错误或遗漏。

官方文档是spec文档。它确实有乘法而不是那里的加法。来自 OpenGL 4.5 规范的第 353/354 页:

The command

    void DrawElementsIndirect( enum mode, enum type, const void *indirect );

is equivalent to

    typedef struct {
        uint count;
        uint instanceCount;
        uint firstIndex;
        int baseVertex;
        uint baseInstance;
    } DrawElementsIndirectCommand;

    if (no element array buffer is bound) {
         generate appropriate error
    } else {
        DrawElementsIndirectCommand *cmd =
            (DrawElementsIndirectCommand *)indirect;
        DrawElementsInstancedBaseVertexBaseInstance(mode,
            cmd->count, type,
            cmd->firstIndex * size-of-type,
            cmd->instanceCount, cmd->baseVertex,
            cmd->baseInstance);
    } 

所以 firstIndex 几乎就是您已经猜到的。它是索引缓冲区(也称为元素数组缓冲区)的偏移量,非常类似于 glDrawElements() 的最后一个元素。唯一的小问题是,在这种情况下,偏移量是以索引为单位测量的,而对于 glDrawElements(),它是以字节为单位测量的。这就是乘以 size-of-type 的地方。

例如,假设您有一个包含 GL_UNSIGNED_SHORT 类型索引的元素数组缓冲区。您希望绘图命令从第 50 个索引开始使用此缓冲区中的索引。对于 glDrawElements(),您将为最后一个参数传入 100,因为偏移量以字节为单位,并且每个索引为两个字节。对于 glDrawElementsIndirect() 中的 firstIndex 值,您将使用 50,因为它是用指数衡量的。规范中乘以 size-of-type,在本例中为 2,解释了这种差异,表示如果将 firstIndex 设置为 50,字节偏移量将为 100,因此与用于的偏移量匹配glDrawElements().