Opengl 数组顶点缓冲区对象必须绑定才能调用此方法

Opengl 数组顶点缓冲区对象必须绑定才能调用此方法,opengl,jogl,Opengl,Jogl,有人知道为什么会抛出此错误吗 当我使用GlenableVertexAttributeArray时,我以为我正在绑定到VBO com.jogamp.opengl.GLException: array vertex_buffer_object must be bound to call this method at jogamp.opengl.gl4.GL4bcImpl.checkBufferObject(GL4bcImpl.java:39146) at jogamp.opengl.

有人知道为什么会抛出此错误吗

当我使用
GlenableVertexAttributeArray
时,我以为我正在绑定到
VBO

com.jogamp.opengl.GLException: array vertex_buffer_object must be bound to call this method
    at jogamp.opengl.gl4.GL4bcImpl.checkBufferObject(GL4bcImpl.java:39146)
    at jogamp.opengl.gl4.GL4bcImpl.checkArrayVBOBound(GL4bcImpl.java:39178)
    at jogamp.opengl.gl4.GL4bcImpl.glVertexAttribPointer(GL4bcImpl.java:37371)
这是我要画的代码

public void draw(final GL2ES2 gl, Matrix4f projectionMatrix, Matrix4f viewMatrix, int shaderProgram, final Vec3 position, final float angle) {

    // enable glsl
    gl.glUseProgram(shaderProgram);

    // enable alpha
    gl.glEnable(GL2ES2.GL_BLEND);
    gl.glBlendFunc(GL2ES2.GL_SRC_ALPHA, GL2ES2.GL_ONE_MINUS_SRC_ALPHA);

    // get handle to glsl variables
    mPositionHandle = gl.glGetAttribLocation(shaderProgram, "vPosition");
    setmColorHandle(gl.glGetUniformLocation(shaderProgram, "vColor"));
    mProj = gl.glGetUniformLocation(shaderProgram, "mProj");
    mView = gl.glGetUniformLocation(shaderProgram, "mView");
    mModel = gl.glGetUniformLocation(shaderProgram, "mModel");

    // perform translations
    getModelMatrix().loadIdentity();
    getModelMatrix().translate(new Vec3(position.x * 60.0f, position.y * 60.0f, position.z * 60.0f));
    getModelMatrix().rotate(angle, 0, 0, 1);

    // set glsl variables
    gl.glUniform4fv(getmColorHandle(), 1, getColorArray(), 0);
    gl.glUniformMatrix4fv(mProj, 1, true, projectionMatrix.getValues(), 0);
    gl.glUniformMatrix4fv(mView, 1, true, viewMatrix.getValues(), 0);
    gl.glUniformMatrix4fv(mModel, 1, true, getModelMatrix().getValues(), 0);

    // Enable a handle to the triangle vertices
    gl.glEnableVertexAttribArray(mPositionHandle);


    // Prepare the triangle coordinate data
    gl.glVertexAttribPointer(
        getmPositionHandle(), 
        COORDS_PER_VERTEX,
        GL2ES2.GL_FLOAT, 
        false,
        vertexStride, 0L); // This is the line that throws error

    // Draw the square
    gl.glDrawElements(
        GL2ES2.GL_TRIANGLES, 
        drawOrder.length,
        GL2ES2.GL_UNSIGNED_SHORT, 
        0L);



    // Disable vertex array
    gl.glDisableVertexAttribArray(mPositionHandle);

    gl.glDisable(GL2ES2.GL_BLEND);
    gl.glUseProgram(0);
}
(我从未将OpenGL与Java一起使用过,所以我将使用C/C++代码,但我希望它能得到很好的理解)

不创建或绑定顶点缓冲区对象

首先,使用
glGenBuffers
创建缓冲区,如下所示:

GLuint bufferID;
glGenBuffers(1, &bufferID);
v1.positionX v1.positionY v1.positionZ v1.colorR v1.colorG v1.colorB
v2.positionX ...
这将分配句柄并将其存储在
bufferID

然后,绑定缓冲区:

glBindBuffers(GL_ARRAY_BUFFER, bufferID);
这使得它成为要使用的“当前”缓冲区

接下来,用数据填充缓冲区。假设
顶点
是以平面格式存储顶点坐标的数组,每个顶点有三个浮点数:

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);
这实际上会将数据放入GPU内存中

然后启用属性数组并设置指针:

glEnableVertexAttribArray(mPositionHandle);
glVertexAttribPointer(mPositionHandle, 3, GL_FLOAT, 0, 0, 0);
这将使
顶点中的数据可用于
mPositionHandle
的顶点属性位置下的着色器程序

glvertexattributepointer
的倒数第二个参数是
stride
。在本例中,它是
0
,因为缓冲区仅包含顶点位置数据。如果要将顶点位置数据和颜色数据打包到同一缓冲区中,如下所示:

GLuint bufferID;
glGenBuffers(1, &bufferID);
v1.positionX v1.positionY v1.positionZ v1.colorR v1.colorG v1.colorB
v2.positionX ...
您需要使用非零的
步幅
<代码>步幅
指定同一类型的一个属性和下一个属性之间的偏移量;如果跨步为
0
,则假定它们是紧密排列的。在这种情况下,您需要将跨距设置为
sizeof(GLfloat)*6
,以便在读取一个顶点的位置后,它将跳过颜色数据以到达下一个顶点,对于颜色也是如此

// (create, bind and fill vertex buffer here)
glEnableVertexAttribArray(location_handle_of_position_data);
glVertexAttribPointer(location_handle_of_position_data, 3, GL_FLOAT, 0, sizeof(GLfloat) * 6, 0);

glEnableVertexAttribArray(location_handle_of_color_data);
glVertexAttribPointer(location_handle_of_color_data, 3, GL_FLOAT, 0, sizeof(GLfloat) * 6, sizeof(GLfloat) * 3);
最后一个参数是第一个属性的偏移量-第一个颜色属性在第三个浮点之后开始

其他考虑:

  • 您应该研究如何使用顶点数组对象。如果没有它们,它可能会工作,也可能不会工作,但按照标准,它们是必需的,并且它们在任何情况下都会简化代码
  • 为了简单起见,此示例代码以浮点形式存储颜色数据,但对于实际使用,最好使用字节

glvertexattributepointer()
指定应使用指定的参数从当前绑定的顶点缓冲区中提取属性的数据。所以你需要打电话:

gl.glBindBuffer(GL_VERTEX_ARRAY, ...);
在调用
glvertexattributepointer()
之前


glEnableVertexAttribArray()
指定应将数组用于顶点属性。否则,将使用一个常量值,该常量值由调用指定,如
glVertexAttrib4f()
。但是它没有指定数组在缓冲区中。更重要的是,除非绑定特定的缓冲区,否则
glvertexattributepointer()
无法知道属性使用哪个缓冲区。

我已经尝试
glGenBuffers
glBindBuffer
glBufferData
之前的
glEnableVertexAttribArray
但我得到的错误与原始错误非常相似<代码>元素顶点\u缓冲区\u对象必须绑定才能调用此方法@bobbyrne01尝试也绑定一个。有些实现不允许您在没有它的情况下做任何事情。