使用OpenGL与LWJGL操作顶点数组对象触发GL_INVALID_OPERATION错误求助
嘿,我一眼就看出你代码里的几个问题了,这些都是刚上手VAO和LWJGL时很容易踩的坑,正是它们触发了GL_INVALID_OPERATION错误:
错误1:混用固定管线与核心管线API
glEnableClientState(GL_VERTEX_ARRAY)是OpenGL旧固定管线的函数,而VAO是核心管线的特性,两者完全不兼容。用VAO的时候,你只需要通过glEnableVertexAttribArray启用对应的顶点属性索引就行,这个旧函数直接删掉就好。错误2:
glEnableVertexAttribArray传参完全错误
你写的glEnableVertexAttribArray(vao)是核心错误!这个函数的参数应该是顶点属性的索引(比如你后面用到的0),而不是VAO的ID。把这里改成glEnableVertexAttribArray(0)才对,传VAO ID必然会触发错误。错误3:设置顶点属性前未绑定VBO
glVertexAttribPointer这个函数会把当前绑定的GL_ARRAY_BUFFER(也就是你的顶点缓冲VBO)和指定的属性索引关联起来。你现在的代码绑定VAO后直接调用这个方法,根本没绑定对应的VBO,OpenGL不知道该从哪个缓冲读取数据,自然会报错。错误4:VAO操作顺序混乱
正确的VAO初始化流程应该是这样的:- 生成并绑定VAO
- 生成并绑定VBO,将顶点数据上传到VBO中
- 调用
glVertexAttribPointer设置顶点属性的格式 - 启用对应的顶点属性索引
- (可选但推荐)解绑VBO
- 解绑VAO
给你一份修正后的代码示例,假设你已经准备好了顶点数据的FloatBuffer:
// 假设已准备好顶点数据缓冲:vertexBuffer int vbo = glGenBuffers(); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, vertexBuffer, GL_STATIC_DRAW); // 正确的VAO初始化流程 int vao = glGenVertexArrays(); glBindVertexArray(vao); // 必须先绑定VBO,再设置顶点属性指针 glBindBuffer(GL_ARRAY_BUFFER, vbo); // 参数说明:属性索引0,每个属性包含count个float值,不进行归一化,步长为Float.SIZE*2,偏移量0 glVertexAttribPointer(0, count, GL_FLOAT, false, Float.SIZE * 2, 0); // 启用属性索引0,而非VAO的ID! glEnableVertexAttribArray(0); // 解绑VBO与VAO glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0);
另外还要注意:确保你的OpenGL上下文是核心模式(如果使用的是3.2及以上版本的核心规范),固定管线的API在核心模式下是被禁用的,这也是混用旧API会报错的原因之一。
内容的提问来源于stack exchange,提问作者Spice

