Java 尝试使用VBO时出错;必须禁用数组顶点“U缓冲区”对象才能调用此方法;

Java 尝试使用VBO时出错;必须禁用数组顶点“U缓冲区”对象才能调用此方法;,java,opengl,language-agnostic,jogl,vbo,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_BUFF

编辑

我已经有效地重写了这个问题,以大大提高其质量-如果必须,请参阅修订日志

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

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),以便如果传入任何点,我都可以看到它们,但这不起作用,我认为这意味着一开始我没有将数据传递到着色器中。

我认为问题在于,当您进行VA绘制时,VBO仍然处于绑定状态。确保无论何时使用glBindBuffer为绘图调用绑定VBO,然后在完成绘图后,将数组/元素\数组缓冲区绑定回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);
您可能还必须在initialize方法中执行这些操作(在生成内容后禁用所有启用的功能,并在传递数据后将内容绑定回零)。否则,当它开始绘制VA时,VBO的东西被启用,所以GL会感到困惑,因为它认为它必须与VBO做些什么,因为它被启用了,但实际上你只想使用VA


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

glvertexattributepointer
有两种操作模式。如果没有VBO绑定,它将使用指向数据的指针作为最后一个参数。如果存在VBO绑定,则最后一个参数是缓冲区中的整数偏移量。在C语言中,无论如何都必须将这个整数转换为指针,但如果有VBO绑定,它就不会被视为指针

在JOGL中,这两种模式通过两个重载实现:(而不是指针)和(而不是指针中的偏移量)

如果使用第一个带有VBO绑定的模式,则会抛出一个错误,因为该模式仅在没有VBO绑定的情况下工作。如果解除VBO的绑定并将
null
传递给最后一个参数,则仍在调用第一个重载:
null
可以匹配
缓冲区
参数,但不能匹配
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\u点
传递到
glpaurements
。这不是有效的组装模式。我不知道这是为了什么(我的OpenGL4知识让我失望)。点装配模式的常数命名为
GL\u points

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

也许你可以试试这个? 不过只是猜测而已

vaoID = new int[2];
gl.glGenVertexArrays(1, vaoID[0], 0);
gl.glBindVertexArray(vaoID[0]);
gl.glGenBuffers(1, vboID[1], 0);
gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, vboID[1]);
FloatBuffer vData = FloatBuffer.allocate(vertexData.length);
vData.put(vertexData);
vData.position(0);
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);

很抱歉,如果这看起来不清楚,但您建议更改绘图代码,但引发错误的是最初缓冲顶点数据的代码。另外,我认为如果我在哪里使用VAO,当我画图时,我只需要绑定那个VAO,VBO和相关的atrtrib指针就会恢复。我的答案确实适用于initialize方法。在开始使用vbo之前,请尝试将顶点数组绑定到0:
glBindVertexArray(0)
(就在
vboID=new int[1];
)我想我发现我只能在调用
gl.glBindBuffer(GL4.gl\u ARRAY\u BUFFER,0)之后调用
glvertexattributepointer
更新了问题以反映我的发现。。。但现在不确定该怎么办:我真的不明白为什么在初始化代码中调用glvertexattributepointer。这是draw代码,不是吗?@Arasumssen如果他正确使用VAO,它将属于初始化代码,在这种情况下,他应该只调用draw方法中的
glBindVertexArray
,而不调用其他任何东西。但是现在他的VAO是无用的。你的初始代码是完整发布的吗?你好像从来没有把它弄坏过。我知道你在想什么。。。但是像
glGenVertexArray
这样的函数需要
int[]
而不仅仅是
int
。我确实尝试过使用
position(0)
而不是
revind()
,但没有什么区别。AFAIR
glvertexattributepointer
仅当最后一个参数不为null时才要求绑定VBO。但是它听起来确实像一个bug。@CatPlusPlus你说得对,它不需要绑定一个bug!我完全忘记了。最后一个参数是1)如果没有绑定VBO,则为指向数据的指针;或者2)如果绑定了VBO,则为偏移量(可笑地转换为指针)。这让我想到在Java中如何将一个随机整数转换成一个“指针”,并导致在非常糟糕的JOGL文档中进行探索。感谢您触发此发现!虽然马丁在《聊天》中花了很多时间帮我解决其他问题,但最终还是成功了。主要是GL_点,而不是GL_点