必须绑定数组vertex_buffer_object才能调用此方法

时间:2015-05-27 09:54:33

标签: opengl jogl

有谁知道为什么会抛出这个错误?

当我使用VBO

时,我认为我对glEnableVertexAttribArray具有约束力
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);
}

2 个答案:

答案 0 :(得分:0)

(我从来没有在Java上使用过OpenGL,所以我会使用C / C ++代码,但我希望它会很好用)

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

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

GLuint bufferID;
glGenBuffers(1, &bufferID);

这会分配一个句柄并将其存储在bufferID

然后,绑定缓冲区:

glBindBuffers(GL_ARRAY_BUFFER, bufferID);

这使它成为"当前"缓冲区使用。

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

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);

这实际上将数据放入GPU内存中。

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

glEnableVertexAttribArray(mPositionHandle);
glVertexAttribPointer(mPositionHandle, 3, GL_FLOAT, 0, 0, 0);

这将使vertices中的数据可用于mPositionHandle的顶点属性位置下的着色器程序。

glVertexAttribPointer的倒数第二个参数是stride。在此示例中,它是0,因为缓冲区仅包含顶点位置数据。如果要将顶点位置数据和颜色数据打包在同一缓冲区中,请执行以下操作:

v1.positionX v1.positionY v1.positionZ v1.colorR v1.colorG v1.colorB
v2.positionX ...

您需要使用非零stridestride指定一个属性与下一个属性之间的偏移量;在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);

最后一个参数是第一个属性的偏移量 - 第一个颜色属性在第三个浮动之后开始。

其他考虑因素:

  • 您应该研究使用顶点阵列对象。没有它们可能会或可能不会工作,但按标准它们是必需的,并且它们在任何情况下都简化了代码。
  • 为简单起见,此示例代码将颜色数据存储在浮点数中,但对于实际使用的字节更为可取。

答案 1 :(得分:0)

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

gl.glBindBuffer(GL_VERTEX_ARRAY, ...);

之前您致电glVertexAttribPointer()

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