JOGL OpenGL只能在奇怪的条件下渲染

时间:2016-04-18 22:01:29

标签: java opengl jogl

我目前正在尝试使用一个非常简单的程序。它只是在黑色背景上显示一个白色十字架。问题是我的十字架的渲染只能在奇怪的条件下工作。这些是我到目前为止所发现的所有条件:

  1. 顶点着色器位置输入的布局必须大于2
  2. glBindVertexArray(0)的任何调用都会导致十字架在调用glBindVertexArray(array)后无法呈现
  3. 我必须在每次抽奖之前致电glUseProgram
  4. 你可能会看到我不知道这里发生了什么。我该如何修复这个错误?

    以下是代码:

    int axesVBO;
    int axesVAO;
    int vert, frag;
    int program;
    
    @Override
    public void display(GLAutoDrawable drawable) {
        System.out.println("Render");
        GL4 gl = drawable.getGL().getGL4();
    
        gl.glClear(GL4.GL_COLOR_BUFFER_BIT | GL4.GL_DEPTH_BUFFER_BIT);
    
        gl.glBindVertexArray(axesVAO);
    
        gl.glUseProgram(program); //Doesnt work without
    
        gl.glDrawArrays(GL4.GL_LINES, 0, 2);
        gl.glDrawArrays(GL4.GL_LINES, 2, 2);
        gl.glBindVertexArray(0); //After this line the cross isn't renderd anymore
    }
    
    @Override
    public void dispose(GLAutoDrawable drawable) {
        GL4 gl = drawable.getGL().getGL4();
    
        gl.glDeleteBuffers(1, IntBuffer.wrap(new int[]{axesVBO}));
        gl.glDeleteVertexArrays(1, IntBuffer.wrap(new int[]{axesVAO}));
        gl.glDeleteProgram(program);
        gl.glDeleteShader(vert);
        gl.glDeleteShader(frag);
    }
    
    @Override
    public void init(GLAutoDrawable drawable) {
        System.out.println("Init");
        GL4 gl = drawable.getGL().getGL4();
    
        IntBuffer buffer = Buffers.newDirectIntBuffer(2);
        gl.glGenBuffers(1, buffer);
        axesVBO = buffer.get(0);
    
        vert = gl.glCreateShader(GL4.GL_VERTEX_SHADER);
        frag = gl.glCreateShader(GL4.GL_FRAGMENT_SHADER);
    
        gl.glShaderSource(vert, 1, new String[]{"#version 410\n in vec2 pos;void main() {gl_Position = vec4(pos, 0, 1);}"}, null);
        gl.glShaderSource(frag, 1, new String[]{"#version 410\n out vec4 FragColor;void main() {FragColor = vec4(1, 1, 1, 1);}"}, null);
    
        gl.glCompileShader(vert);
        gl.glCompileShader(frag);
    
        if(GLUtils.getShaderiv(gl, vert, GL4.GL_COMPILE_STATUS) == GL.GL_FALSE) {
            System.out.println("Vertex shader compilation failed:");
            System.out.println(GLUtils.getShaderInfoLog(gl, vert));
        } else {
            System.out.println("Vertex shader compilation sucessfull");
        }
    
        if(GLUtils.getShaderiv(gl, frag, GL4.GL_COMPILE_STATUS) == GL.GL_FALSE) {
            System.out.println("Fragment shader compilation failed:");
            System.out.println(GLUtils.getShaderInfoLog(gl, frag));
        } else {
            System.out.println("Fragment shader compilation sucessfull");
        }
    
        program = gl.glCreateProgram();
    
        gl.glAttachShader(program, vert);
        gl.glAttachShader(program, frag);
    
        gl.glBindAttribLocation(program, 2, "pos"); //Only works when location is > 2
        gl.glLinkProgram(program);
    
        if(GLUtils.getProgramiv(gl, program, GL4.GL_LINK_STATUS) == GL.GL_FALSE) {
            System.out.println("Program linking failed:");
            System.out.println(GLUtils.getProgramInfoLog(gl, program));
        } else {
            System.out.println("Program linking sucessfull");
        }
    
        gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, axesVBO);
        gl.glBufferData(GL4.GL_ARRAY_BUFFER, Float.BYTES * 8, FloatBuffer.wrap(new float[]{-1f, 0, 1f, 0, 0, 1f, 0, -1f}), GL4.GL_STATIC_DRAW);
    
        gl.glUseProgram(program);
    
        buffer.clear();
        gl.glGenVertexArrays(1, buffer);
        axesVAO = buffer.get();
        gl.glBindVertexArray(axesVAO);
    
        int pos = gl.glGetAttribLocation(program, "pos");
        gl.glEnableVertexAttribArray(pos);
    
        gl.glBindBuffer(GL4.GL_ARRAY_BUFFER, axesVBO);
        gl.glVertexAttribPointer(pos, 2, GL4.GL_FLOAT, false, 0, 0);
        //Commented out for testing reasons (doesnt work when active)
        //gl.glBindVertexArray(0);
    
        gl.glClearColor(0f, 0f, 0f, 1f);
    }
    

1 个答案:

答案 0 :(得分:1)

你想出的条件看起来很奇怪。无论如何,一般来说,拥有干净简单的代码有助于避免令人讨厌的错误。开始干净简单,然后建立它:)

很少考虑:

  • 请勿将int用于vbo和vao,直接使用直接缓冲区
  • 如果仅在vert中使用它们,则不需要声明全局fraginit,而是在方法中将其声明为
  • 更喜欢使用jogl实用程序GLBuffers.newDirect*Buffer(...)
  • 生成直接缓冲区
  • 至少在开始时,更喜欢使用jogl实用程序(ShaderCode.createShaderProgram)来编译着色器,它可以减轻您的工作量和潜在的错误,并且可以对任何步骤进行更深入的检查在整个着色器创建期间(有时甚至太多,但现在着色器编译得如此之快并不重要)
  • 如果你有ARB_explicit_attrib_location,可以查看gl4.isExtensionAvailable("GL_ARB_explicit_attrib_location");,随时随地使用它,它可以避免很多潜在的错误和任何位置的开销(例如glBindAttribLocation }和glGetAttribLocation
  • 最好将直接缓冲区传递给glBufferData,这样jogl就不必自己在下面创建它,你可以跟踪它以释放它
  • 保持init清洁可读。你把很多东西混合在一起。例如,您在开始时生成vbo,然后创建程序,然后将数据上传到vbo。
  • gl.glUseProgram(program);中没有任何意义init,除非您的想法是绑定它并让它受约束。无论如何,通常,程序是渲染调用之前的初始化阶段的一部分,因此最好在display()中移动它。
  • 首选glClearBufferglClear
  • gl.glDrawArrays(GL4.GL_LINES, 0, 2);没有效用,因为您将零作为顶点数传递
  • 如果您需要灵感,请查看此Hello Triangle