我有两个使用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的错误吗?
答案 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);
然后它运作得很好。