简体   繁体   English

OpenGL使用单个VBO渲染多个对象,并使用另一个VBO渲染updata对象的矩阵

[英]OpenGL render multiple objects using single VBO and updata object's matrices using another VBO

So, I need the way to render multiple objects(not instances) using one draw call. 因此,我需要一种使用一次绘制调用来呈现多个对象(而非实例)的方法。 Actually I know how to do this, just to place data into single vbo/ibo and render, using glDrawElements. 实际上,我知道如何做到这一点,只是使用glDrawElements将数据放入单个vbo / ibo中并进行渲染。

The question is: what is efficient way to update uniform data without setting it up for every single object, using glUniform...? 问题是:使用glUniform ...无需为每个对象设置统一数据即可更新统一数据的有效方法是什么?

How can I setup one buffer containing all uniform data of dozens of objects, include MVP matrices, bind it and perform render using single draw call? 如何设置一个包含数十个对象的所有统一数据,包括MVP矩阵,绑定它并使用一次draw调用执行渲染的缓冲区? I tried to use UBOs, but it's not what I need at all. 我尝试使用UBO,但这根本不是我所需要的。

For rendering instances we just place uniform data, including matrices, at another VBO and set up attribute divisor using glVertexAttribDivisor, but it only works for instances. 对于渲染实例,我们仅将统一的数据(包括矩阵)放置在另一个VBO上,并使用glVertexAttribDivisor设置属性除数,但它仅适用于实例。

Is there a way to do that I want in OpenGL? 有什么方法可以在OpenGL中进行吗? If not, what can I do to overcome overheads of setting uniform data for dozens of objects? 如果没有,我该如何克服为数十个对象设置统一数据的开销?

For example like this: 例如这样:

{
    // setting up VBO
    glGenBuffers(1, &vbo);
    glBindBuffer(vbo);
    glBufferData(..., data_size);

    // setup buffer
    for(int i = 0; i < objects_num; i++)
        glBufferSubData(...offset, size, &(objects[i]));

    // the same for IBO
    .........
    // when setup some buffer, that will store all uniforms, for every object
    .........
    glDrawElements(...);
}

Thanks in advance for helping. 在此先感谢您的帮助。

If you're ok with requiring OpenGL 4.3 or higher, I believe you can render this with a single draw call using glMultiDrawElementsIndirect() . 如果您可以要求使用OpenGL 4.3或更高版本,我相信您可以使用glMultiDrawElementsIndirect()通过一次绘制调用来渲染此图像。 This allows you to essentially make multiple draw calls with a single API call. 这实际上使您可以通过单个API调用进行多个绘制调用。 Each sub-call is defined by values in a struct of the form: 每个子调用均由以下形式的结构中的值定义:

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

Since you do not want to draw multiple instances of the same vertices, you use 1 for the instanceCount in each draw call. 由于您不想绘制相同顶点的多个实例,因此在每个绘制调用中对instanceCount使用1。 The key idea is that you can still use instancing by specifying a different baseInstance value for each one. 关键思想是您仍然可以通过为每个实例指定不同的baseInstance值来使用实例化。 So each object will have a different gl_InstanceID value, and you can use instanced attributes for the values (matrices, etc) that you want to vary per object. 因此,每个对象将具有不同的gl_InstanceID值,并且您可以将实例化属性用于要针对每个对象而变化的值(矩阵等)。

So if you currently have a rendering loop: 因此,如果您当前有一个渲染循环:

for (int k = 0; k < objectCount; ++k) {
    // set uniforms for object k.
    glDrawElements(GL_TRIANGLES, object[k].indexCount,
                   GL_UNSIGNED_INT, object[k].indexOffset * sizeof(GLuint));
}

you would instead fill an array of the struct defined above with the arguments: 您可以使用以下参数填充上面定义的结构数组:

DrawElementsIndirectCommand cmds[objectCount];
for (int k = 0; k < objectCount; ++k) {
    cmds[k].count = object[k].indexCount;
    cmds[k].instanceCount = 1;
    cmds[k].firstIndex = object[k].indexOffset;
    cmds[k].baseVertex = 0;
    cmds[k].baseInstance = k;
}

// Rest of setup.

glMultiDrawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, 0, objectCount, 0);

I didn't provide code for the full setup above. 我没有为上面的完整设置提供代码。 The key steps include: 关键步骤包括:

  • Drop the cmds array into a buffer, and bind it as GL_DRAW_INDIRECT_BUFFER . cmds数组放入缓冲区中,并将其绑定为GL_DRAW_INDIRECT_BUFFER
  • Store the per-object values in a VBO. 将每个对象的值存储在VBO中。 Set up the corresponding vertex attributes, which includes specifying them as instanced with glVertexAttribDivisor(1) . 设置相应的顶点属性,包括使用glVertexAttribDivisor(1)实例指定它们。
  • Set up the per-vertex attributes as usual. 照常设置每个顶点的属性。
  • Set up the index buffer as usual. 照常设置索引缓冲区。

For this to work, the indices for all the objects will have to be in the same index buffer, and the values for each attribute will have to be in the same VBO across all objects. 为此,所有对象的索引必须位于同一索引缓冲区中,并且每个属性的值必须在所有对象之间均位于同一VBO中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM