OpenGL/JOGL 投掷 GL_INVALID_OPERATION
OpenGL/JOGL throwing GL_INVALID_OPERATION
我正在为我正在开发的游戏编写关卡编辑器。我使用 JOGL,但我似乎遇到了问题。我习惯了 LWJGL openGL 调用并且调整到核心 opengl 有点令人困惑,因为 lwjgl 似乎简化了很多东西。
所以我的问题是我创建了一个包含 vao ID/name 和顶点数的模型以及一个创建模型和渲染器的模型加载器。渲染器目前不是批处理的。我稍后会处理它。问题是 opengl 抛出 GL_INVALID_OPERATION 错误。不确定是什么原因造成的。其他一切,包括我为测试环境而绘制的基本三角形,都可以正常工作,所以我的加载器或渲染器中似乎有问题。
代码如下:
型号:
public class JoglModel {
private int vaoID;
private int vertexCount;
public JoglModel(int vertexCount, int vaoID) {
this.vertexCount = vertexCount;
this.vaoID = vaoID;
}
public int getVertexCount() {
return vertexCount;
}
public int getVaoID() {
return vaoID;
}
}
加载程序:
public class ModelLoader {
private GL2 gl;
private List<int[]> vaos = new ArrayList<int[]>();
private List<int[]> vbos = new ArrayList<int[]>();
public ModelLoader(GL2 gl){
this.gl = gl;
}
public JoglModel loadToVao(float[] positions){
int vaoID = createVAO();
storeDataInAttributeList(0,positions);
unbind();
return new JoglModel(vaoID,positions.length/3);
}
private int createVAO(){
int[] vaoID = new int[1];
gl.glGenVertexArrays(vaoID.length, vaoID, 0);
vaos.add(vaoID);
gl.glBindVertexArray(vaoID[0]);
return vaoID[0];
}
private void storeDataInAttributeList(int attributeNumber,float[] data){
int[] vboID = new int[1];
gl.glGenBuffers(vboID.length,vboID,0);
vbos.add(vboID);
gl.glBindBuffer(gl.GL_ARRAY_BUFFER,vboID[0]);
FloatBuffer floatBuffer = createFloatBuffer(data);
gl.glBufferData(gl.GL_ARRAY_BUFFER,floatBuffer.remaining(),floatBuffer,gl.GL_STATIC_DRAW);
gl.glVertexAttribPointer(attributeNumber,3,gl.GL_FLOAT,false,0,0);
gl.glBindBuffer(gl.GL_ARRAY_BUFFER,0);
}
private FloatBuffer createFloatBuffer(float[] data){
FloatBuffer floatBuffer = FloatBuffer.allocate(data.length);
floatBuffer.put(data);
floatBuffer.flip();
return floatBuffer;
}
private void unbind(){}
public void clear(){
for(int[] vao : vaos){
gl.glDeleteVertexArrays(vao.length,vao,0);
}
for(int[] vbo: vbos){
gl.glDeleteBuffers(vbo.length,vbo,0);
}
vaos.clear();
vbos.clear();
}
}
渲染器:
public class JoglRenderer {
私人 GL2 gl;
public JoglRenderer(GL2 gl){
this.gl = gl;
}
public void begin(){
gl.glClearColor(1f,0f,0f,1f);
gl.glClear(gl.GL_CLEAR_BUFFER);
}
public void render(JoglModel joglModel){
gl.glBindVertexArray(joglModel.getVaoID());
gl.glEnableVertexAttribArray(0);
gl.glDrawArrays(gl.GL_TRIANGLES,0,joglModel.getVertexCount());
gl.glDisableVertexAttribArray(0);
gl.glBindVertexArray(0);
/*
gl.glBegin(gl.GL_TRIANGLES);
gl.glColor3f(1, 0, 0);
gl.glVertex2f(-1, -1);
gl.glColor3f(0, 1, 0);
gl.glVertex2f(0, 1);
gl.glColor3f(0, 0, 1);
gl.glVertex2f(1, -1);
gl.glEnd();
*/
}
public void checkError() {
String errorString = "";
int error = gl.glGetError();
if (error != GL.GL_NO_ERROR) {
switch (error) {
case GL.GL_INVALID_ENUM:
errorString = "GL_INVALID_ENUM";
break;
case GL.GL_INVALID_VALUE:
errorString = "GL_INVALID_VALUE";
break;
case GL.GL_INVALID_OPERATION:
errorString = "GL_INVALID_OPERATION";
break;
case GL.GL_INVALID_FRAMEBUFFER_OPERATION:
errorString = "GL_INVALID_FRAMEBUFFER_OPERATION";
break;
case GL.GL_OUT_OF_MEMORY:
errorString = "GL_OUT_OF_MEMORY";
break;
default:
errorString = "UNKNOWN";
break;
}
}
System.out.println(errorString);
}
}
注释掉的三角形部分工作得很好。清除屏幕方法似乎也有错误,但这不是我现在关心的问题。谁能指出问题出在哪里?
谢谢
(编辑)
所以我弄清楚了opengl错误。我不小心将 vaoID 作为顶点数传递,反之亦然。所以我修复了错误消失了。但是什么都没有被渲染。有什么想法吗?
我在这里写了一些注意事项,因为评论太短了:
loadToVao
可能会误导你,你不会将任何东西加载到 vao 中,vao 有助于记住启用了哪些顶点属性数组,它们的 layout/format 和他们指的是哪个 vbo,这样你就不必在每一帧都调用它们。它还可以存储绑定的元素数组。所以 glEnableVertexAttribArray
和 glDisableVertexAttribArray
不应该进入 render()
函数
渲染器应该始终默认存在,所以我建议有一个主渲染器并在那里初始化你的渲染器(GLEventListener
)
我不会在 createVAO
中绑定 vao
不存储 GL
元素。保持瞬态(每次都作为参数传递)或从 GLContext
获取。第一个选项可能会增加复杂性(因为每个 gl 调用都需要从 class 实现 GLEventListener
的 GL
对象)但简化了调试(因为你确实知道 gl 调用的执行顺序)。
如果你只需要一个 vao,避免为此创建一个 List
,vbo 也是如此。
我建议您使用 static final int
变量来保存顶点属性索引。它提高了可读性并避免了潜在的错误。
除非你不需要直接缓冲区,使用GLBuffers
分配(直接)缓冲区。
那是什么gl.GL_FLOAT
?我从没见过。请改用 Float.BYTES
或 GLBuffers.SIZEOF_FLOAT
。
正如@BDL 已经说过的那样,查看 glClear
并像 here 一样调用 checkError
,每次传递一个不同的字符串,以便您可以轻松找到如果出现错误,这是有问题的调用。
Jogl 确实有一个 GL_COLOR_BUFFER_BIT
,只需编写它并调用自动完成,您的 IDE 应该会建议您正确的位置或自动插入正确的 import
如果你设置得当
它看起来也缺少(也许你没有报告)是 glVertexAttribPointer
如果还是不行,回到基本的测试三角形,确保它有效,然后从那里开始构建。将它移出自己的 class 渲染器,用更多的几何图形丰富它,使用索引绘图,ecc。每一步都控制它起作用,如果不起作用,那么错误就出在你最后的修改上。
我正在为我正在开发的游戏编写关卡编辑器。我使用 JOGL,但我似乎遇到了问题。我习惯了 LWJGL openGL 调用并且调整到核心 opengl 有点令人困惑,因为 lwjgl 似乎简化了很多东西。
所以我的问题是我创建了一个包含 vao ID/name 和顶点数的模型以及一个创建模型和渲染器的模型加载器。渲染器目前不是批处理的。我稍后会处理它。问题是 opengl 抛出 GL_INVALID_OPERATION 错误。不确定是什么原因造成的。其他一切,包括我为测试环境而绘制的基本三角形,都可以正常工作,所以我的加载器或渲染器中似乎有问题。
代码如下: 型号:
public class JoglModel {
private int vaoID;
private int vertexCount;
public JoglModel(int vertexCount, int vaoID) {
this.vertexCount = vertexCount;
this.vaoID = vaoID;
}
public int getVertexCount() {
return vertexCount;
}
public int getVaoID() {
return vaoID;
}
}
加载程序:
public class ModelLoader {
private GL2 gl;
private List<int[]> vaos = new ArrayList<int[]>();
private List<int[]> vbos = new ArrayList<int[]>();
public ModelLoader(GL2 gl){
this.gl = gl;
}
public JoglModel loadToVao(float[] positions){
int vaoID = createVAO();
storeDataInAttributeList(0,positions);
unbind();
return new JoglModel(vaoID,positions.length/3);
}
private int createVAO(){
int[] vaoID = new int[1];
gl.glGenVertexArrays(vaoID.length, vaoID, 0);
vaos.add(vaoID);
gl.glBindVertexArray(vaoID[0]);
return vaoID[0];
}
private void storeDataInAttributeList(int attributeNumber,float[] data){
int[] vboID = new int[1];
gl.glGenBuffers(vboID.length,vboID,0);
vbos.add(vboID);
gl.glBindBuffer(gl.GL_ARRAY_BUFFER,vboID[0]);
FloatBuffer floatBuffer = createFloatBuffer(data);
gl.glBufferData(gl.GL_ARRAY_BUFFER,floatBuffer.remaining(),floatBuffer,gl.GL_STATIC_DRAW);
gl.glVertexAttribPointer(attributeNumber,3,gl.GL_FLOAT,false,0,0);
gl.glBindBuffer(gl.GL_ARRAY_BUFFER,0);
}
private FloatBuffer createFloatBuffer(float[] data){
FloatBuffer floatBuffer = FloatBuffer.allocate(data.length);
floatBuffer.put(data);
floatBuffer.flip();
return floatBuffer;
}
private void unbind(){}
public void clear(){
for(int[] vao : vaos){
gl.glDeleteVertexArrays(vao.length,vao,0);
}
for(int[] vbo: vbos){
gl.glDeleteBuffers(vbo.length,vbo,0);
}
vaos.clear();
vbos.clear();
}
}
渲染器:
public class JoglRenderer {
私人 GL2 gl;
public JoglRenderer(GL2 gl){
this.gl = gl;
}
public void begin(){
gl.glClearColor(1f,0f,0f,1f);
gl.glClear(gl.GL_CLEAR_BUFFER);
}
public void render(JoglModel joglModel){
gl.glBindVertexArray(joglModel.getVaoID());
gl.glEnableVertexAttribArray(0);
gl.glDrawArrays(gl.GL_TRIANGLES,0,joglModel.getVertexCount());
gl.glDisableVertexAttribArray(0);
gl.glBindVertexArray(0);
/*
gl.glBegin(gl.GL_TRIANGLES);
gl.glColor3f(1, 0, 0);
gl.glVertex2f(-1, -1);
gl.glColor3f(0, 1, 0);
gl.glVertex2f(0, 1);
gl.glColor3f(0, 0, 1);
gl.glVertex2f(1, -1);
gl.glEnd();
*/
}
public void checkError() {
String errorString = "";
int error = gl.glGetError();
if (error != GL.GL_NO_ERROR) {
switch (error) {
case GL.GL_INVALID_ENUM:
errorString = "GL_INVALID_ENUM";
break;
case GL.GL_INVALID_VALUE:
errorString = "GL_INVALID_VALUE";
break;
case GL.GL_INVALID_OPERATION:
errorString = "GL_INVALID_OPERATION";
break;
case GL.GL_INVALID_FRAMEBUFFER_OPERATION:
errorString = "GL_INVALID_FRAMEBUFFER_OPERATION";
break;
case GL.GL_OUT_OF_MEMORY:
errorString = "GL_OUT_OF_MEMORY";
break;
default:
errorString = "UNKNOWN";
break;
}
}
System.out.println(errorString);
}
}
注释掉的三角形部分工作得很好。清除屏幕方法似乎也有错误,但这不是我现在关心的问题。谁能指出问题出在哪里?
谢谢
(编辑) 所以我弄清楚了opengl错误。我不小心将 vaoID 作为顶点数传递,反之亦然。所以我修复了错误消失了。但是什么都没有被渲染。有什么想法吗?
我在这里写了一些注意事项,因为评论太短了:
loadToVao
可能会误导你,你不会将任何东西加载到 vao 中,vao 有助于记住启用了哪些顶点属性数组,它们的 layout/format 和他们指的是哪个 vbo,这样你就不必在每一帧都调用它们。它还可以存储绑定的元素数组。所以glEnableVertexAttribArray
和glDisableVertexAttribArray
不应该进入render()
函数渲染器应该始终默认存在,所以我建议有一个主渲染器并在那里初始化你的渲染器(
GLEventListener
)我不会在
createVAO
中绑定 vao
不存储
GL
元素。保持瞬态(每次都作为参数传递)或从GLContext
获取。第一个选项可能会增加复杂性(因为每个 gl 调用都需要从 class 实现GLEventListener
的GL
对象)但简化了调试(因为你确实知道 gl 调用的执行顺序)。如果你只需要一个 vao,避免为此创建一个
List
,vbo 也是如此。我建议您使用
static final int
变量来保存顶点属性索引。它提高了可读性并避免了潜在的错误。除非你不需要直接缓冲区,使用
GLBuffers
分配(直接)缓冲区。那是什么
gl.GL_FLOAT
?我从没见过。请改用Float.BYTES
或GLBuffers.SIZEOF_FLOAT
。正如@BDL 已经说过的那样,查看
glClear
并像 here 一样调用checkError
,每次传递一个不同的字符串,以便您可以轻松找到如果出现错误,这是有问题的调用。Jogl 确实有一个
GL_COLOR_BUFFER_BIT
,只需编写它并调用自动完成,您的 IDE 应该会建议您正确的位置或自动插入正确的import
如果你设置得当它看起来也缺少(也许你没有报告)是
glVertexAttribPointer
如果还是不行,回到基本的测试三角形,确保它有效,然后从那里开始构建。将它移出自己的 class 渲染器,用更多的几何图形丰富它,使用索引绘图,ecc。每一步都控制它起作用,如果不起作用,那么错误就出在你最后的修改上。