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,这样你就不必在每一帧都调用它们。它还可以存储绑定的元素数组。所以 glEnableVertexAttribArrayglDisableVertexAttribArray 不应该进入 render() 函数

  • 渲染器应该始终默认存在,所以我建议有一个主渲染器并在那里初始化你的渲染器(GLEventListener

  • 我不会在 createVAO

  • 中绑定 vao
  • 不存储 GL 元素。保持瞬态(每次都作为参数传递)或从 GLContext 获取。第一个选项可能会增加复杂性(因为每个 gl 调用都需要从 class 实现 GLEventListenerGL 对象)但简化了调试(因为你确实知道 gl 调用的执行顺序)。

  • 如果你只需要一个 vao,避免为此创建一个 List,vbo 也是如此。

  • 我建议您使用 static final int 变量来保存顶点属性索引。它提高了可读性并避免了潜在的错误。

  • 除非你不需要直接缓冲区,使用GLBuffers分配(直接)缓冲区。

  • 那是什么gl.GL_FLOAT?我从没见过。请改用 Float.BYTESGLBuffers.SIZEOF_FLOAT

  • 正如@BDL 已经说过的那样,查看 glClear 并像 here 一样调用 checkError,每次传递一个不同的字符串,以便您可以轻松找到如果出现错误,这是有问题的调用。

  • Jogl 确实有一个 GL_COLOR_BUFFER_BIT,只需编写它并调用自动完成,您的 IDE 应该会建议您正确的位置或自动插入正确的 import 如果你设置得当

  • 它看起来也缺少(也许你没有报告)是 glVertexAttribPointer

  • 如果还是不行,回到基本的测试三角形,确保它有效,然后从那里开始构建。将它移出自己的 class 渲染器,用更多的几何图形丰富它,使用索引绘图,ecc。每一步都控制它起作用,如果不起作用,那么错误就出在你最后的修改上。