尝试使用VBO时出错“必须禁用数组vertex_buffer_object才能调用此方法”

时间:2011-12-06 10:44:44

标签: java opengl language-agnostic jogl vbo

修改

我已经有效地重写了这个问题,以便大大提高其质量 - 如果你必须

,请参阅修订日志

当我尝试创建顶点缓冲区时,我已将问题缩小到程序的初始化阶段。我目前使用的代码是......

vaoID = new int[1];
gl.glGenVertexArrays(1, vaoID, 0);
gl.glBindVertexArray(vaoID[0]);
vboID = new int[1];
gl.glGenBuffers(1, vboID, 0);
gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, vboID[0]);
FloatBuffer vData = FloatBuffer.allocate(vertexData.length);
vData.put(vertexData);
vData.rewind();
gl.glBufferData(GL4.GL_ARRAY_BUFFER, vData.capacity() * (Float.SIZE / 8), vData, GL4.GL_STATIC_DRAW);
gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, 0); // With out this line my code throws the exception
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(0, 4, GL.GL_FLOAT, false, 0, null); // This is the line where the exception is thrown
gl.glBindVertexArray(0);

所以是的,目前我的代码能够在没有崩溃的情况下运行,但它必须在某些地方出错,因为我无法将其渲染。为了缓冲索引数据,我使用这个代码,它在运行时成功完成

gl.glGenBuffers(1, bufferIDs, 0);
gl.glBindBuffer(GL4.GL_ELEMENT_ARRAY_BUFFER, bufferIDs[0]);
ShortBuffer iData = ShortBuffer.allocate(indexData.length);
iData.put(indexData);
iData.rewind();
indexCount = iData.capacity();
gl.glBufferData(GL4.GL_ELEMENT_ARRAY_BUFFER, indexCount * (Short.SIZE / 8), iData, GL4.GL_STATIC_DRAW);
gl.glBindBuffer(GL4.GL_ELEMENT_ARRAY_BUFFER, 0);

然后说到绘图,我执行以下步骤,我认为这不重要,因为我确信我首先仍然没有正确缓冲

// first I bind my VAO
gl.glBindVertexArray(vaoID[0]);
// then bind, draw, unbind the index buffer
gl.glBindBuffer(GL4.GL_ELEMENT_ARRAY_BUFFER, bufferIDs[0]);
gl.glDrawElements(GL4.GL_POINT, indexCount, GL4.GL_UNSIGNED_SHORT, 0);
gl.glBindBuffer(GL4.GL_ELEMENT_ARRAY_BUFFER, 0);
// finally I unbind the VAO
gl.glBindVertexArray(0);

我很确定这是渲染缓冲几何的正确过程。我通过使用一些立即的绘图命令确认我的着色器代码是正确和有效的,所以我有完整的管道,它似乎我没有提供数据。作为一个兴趣点,我也尝试编辑我的顶点着色器将所有点设置为(0,0,0,1),这样如果传入的任何点,我应该看到它们,但这不起作用,我这意味着我不是首先将数据传递到我的着色器中。

2 个答案:

答案 0 :(得分:6)

glVertexAttribPointer有两种操作模式。如果没有VBO绑定,则它将指向数据的指针作为最后一个参数。如果存在VBO绑定,则最后一个参数是缓冲区中的整数偏移量。在C中,您必须将此整数转换为指针,但如果存在VBO绑定,则不会将其视为指针。

在JOGL中,这两种模式通过两个重载来实现:one that takes a Buffer(而不是指针)和one that takes a long(而不是投射到指针中的偏移量)。

如果你使用带有VBO绑定的第一个它会抛出一个错误,因为这是只有在没有VBO绑定的情况下才能工作的模式。如果您取消绑定VBO并将null传递给最后一个参数,则仍然会调用第一个重载:null可以匹配Buffer参数,但不能匹配long。对于这种情况,JOGL似乎没有类似的验证。这可能会将其视为偏移量0,但它也将存储0作为VBO来查找数据。也就是说,根本没有VBO。

你需要做的是,使用原始代码,即使用VBO绑定,调用带偏移量的重载:

//pass a long instead of a null Buffer
gl.glVertexAttribPointer(0, 4, GL.GL_FLOAT, false, 0, 0L);

另外还有一个问题就是不让任何东西渲染。您已将GL4.GL_POINT传递给glDrawElements。那不是有效的装配模式。我不知道它是什么(我的OpenGL 4知识让我失望)。点汇编模式的常量名为GL_POINTS

gl.glDrawElements(GL.GL_POINTS, indexCount, GL4.GL_UNSIGNED_SHORT, 0);

答案 1 :(得分:0)

我认为问题是当你去做VA抽奖时你的VBO仍然受约束。确保无论何时使用glBindBuffer绑定VBO进行绘制调用,然后在完成绘制后,将ARRAY / ELEMENT_ARRAY缓冲区绑定回0.还要确保禁用任何客户端状态或attrib数组你已经完成了平局。

// vbo draw
gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, bufferID[0]);
gl.glEnableVertexAttribArray(0);
gl.glVertexAttribPointer(0, 4, GL.GL_FLOAT, false, 0, null); // I know that this should be changed, but can't get code to run to this as can't buffer data in first place
gl.glDisableVertexAttribArray(0);
gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, 0);

// ibo draw
gl.glBindBuffer(GL4.GL_ELEMENT_ARRAY_BUFFER, bufferIDs[0]);
gl.glDrawElements(GL4.GL_POINT, indexCount, GL4.GL_UNSIGNED_SHORT, 0);
gl.glBindBuffer(GL4.GL_ELEMENT_ARRAY_BUFFER, 0);

您可能还必须在初始化方法中执行这些操作(禁用在生成内容后启用的所有内容,并在传递数据后将内容绑定回零)。否则,当它绘制VA时,VBO的东西就会被启用,因此GL会因为认为它必须对VBO做一些事情而感到困惑,因为它已启用但实际上你只想使用VA。

这是我对你的问题的最佳猜测。如果没有解决,请随意评论我的帖子。