使用glMultiDrawArraysIndirect和间接缓冲区时出错

时间:2015-03-12 07:43:41

标签: opengl glsl jogl

我有两个使用glMultiDrawArraysIndirect()渲染的对象(A和B)。每个对象都有一个setupBuffers()方法,用于创建,绑定vao,然后创建和绑定间接缓冲区,实例ID缓冲区,顶点缓冲区和纹理坐标缓冲区。 (使用JOGL)

问题是:如果在调用B中的setupBuffers()之前调用对象A的setupBuffers(),那么只会绘制B;如果在调用A中的setupBuffers()之前调用对象B的setupBuffers(),则只会绘制A。 (没有例外。)存储的数据应该是正确的,因为我已经测试了它们。

对象A:

protected void setupBuffers()
{
    gl.glGenVertexArrays(1, vaoBuff);
    gl.glBindVertexArray(vaoBuff.get(0));

    gl.glGenBuffers(4, vboBuff);

    //bind indirect buffer object
    gl.glBindBuffer(GL4.GL_DRAW_INDIRECT_BUFFER, vboBuff.get(0));
    gl.glBufferData(GL4.GL_DRAW_INDIRECT_BUFFER, instanceCount * 4 * Integer.SIZE / 8, null, GL4.GL_STATIC_DRAW);
    gl.glBufferSubData(...);

    //bind draw instance ID in the shader with a buffer object
    gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, vboBuff.get(1));
    gl.glBufferData(GL4.GL_ARRAY_BUFFER, instanceCount * Integer.SIZE / 8, drawIndexBuff, GL4.GL_STATIC_DRAW);
    gl.glVertexAttribIPointer(d_idLoc, 1, GL4.GL_UNSIGNED_INT, 0, 0);
    gl.glVertexAttribDivisor(d_idLoc, 1);
    gl.glEnableVertexAttribArray(d_idLoc);

    //bind vertex data buffer object
    gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, vboBuff.get(2));
    gl.glBufferData(GL4.GL_ARRAY_BUFFER, instanceCount / column_subdivision * vertBuffSize * Float.SIZE / 8, null, GL4.GL_STATIC_DRAW);
    gl.glBufferSubData(...);
    gl.glVertexAttribPointer(verPosLoc, 3, GL4.GL_FLOAT, false, 0, 0);
    gl.glEnableVertexAttribArray(verPosLoc);

    //bind texture coordinate data buffer object
    gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, vboBuff.get(3));
    gl.glBufferData(GL4.GL_ARRAY_BUFFER, instanceCount / column_subdivision * texBuffSize * Float.SIZE / 8, null, GL4.GL_STATIC_DRAW);
    gl.glBufferSubData(...);
    gl.glVertexAttribPointer(tc_inLoc, 2, GL4.GL_FLOAT, false, 0, 0);
    gl.glEnableVertexAttribArray(tc_inLoc);
}

绘图方法:

gl.glBindVertexArray(vaoBuff.get(0));
gl.glMultiDrawArraysIndirect(GL4.GL_TRIANGLE_STRIP, 0, instanceCount, 0);

对象B:

(方法' setupBuffers()'非常类似于A)

绘图方法:

gl.glBindVertexArray(vaoBuff.get(0));
gl.glMultiDrawArraysIndirect(GL4.GL_PATCHES, 0, instanceCount, 0);

有什么想法吗?

添加了: 现在我找到导致该问题的那一行:

gl.glBindBuffer(GL4.GL_DRAW_INDIRECT_BUFFER, vboBuff.get(0));

用于绑定间接缓冲区的方法在Object A& A中被调用一次。 B,导致了这个问题,但我不明白为什么。这是为什么?使用OpenGL是否相同(我使用JOGL)?或者这是JOGL的错误吗?

2 个答案:

答案 0 :(得分:2)

您自己的答案部分描述了问题的根本原因,这很有意义。 GL_DRAW_INDIRECT_BUFFER绑定确实不是VAO状态的一部分。这一点得到了规范的证实。表23.5中列出了相应的状态(DRAW_INDIRECT_BUFFER_BINDING),标题为“顶点数组数据(不在顶点数组对象中)”。

但您建议的解决方案对我来说并不理想。在每次绘制调用之前在间接缓冲区上调用glBufferData()将首先破坏将数据存储在缓冲区中的目的。我们的想法是,您可以重复使用数据,同时保留在GPU可以有效访问的内存中。

在每次绘制调用之前,您需要做的就是绑定缓冲区。然后,绘图的调用顺序如下所示:

gl.glBindVertexArray(vaoBuff.get(0)); 
gl.glBindBuffer(GL4.GL_DRAW_INDIRECT_BUFFER, vboBuff.get(0));
gl.glMultiDrawArraysIndirect(GL4.GL_PATCHES, 0, instanceCount, 0);

答案 1 :(得分:1)

最后解决了这个问题。 GL_DRAW_INDIRECT_BUFFER绑定点不是顶点数组对象状态的一部分。它的全球背景状态。因此,在从该缓冲区执行间接操作之前,我必须将其设置为我想要拉出的缓冲区(将上面的代码更改为):

gl.glBindVertexArray(vaoBuff.get(0)); 
gl.glBindBuffer(GL4.GL_DRAW_INDIRECT_BUFFER, vboBuff.get(0));
gl.glMultiDrawArraysIndirect(GL4.GL_PATCHES, 0, instanceCount, 0); 

然后它运作得很好。