glVertexAttribPointer出现JOGL错误

时间:2014-06-30 09:47:58

标签: java opengl jogl vao

我正在使用下面的代码(使用VAO(顶点缓冲区对象)和glDrawArraysInstanced方法)

如果我设置useVao = false,那就没关系。但是当我将其设置为true时,我有以下异常:

  

javax.media.opengl.GLException:线程[AWT-EventQueue-0,6,main] glGetError()在调用glVertexAttribPointer后返回以下错误代码(GLArrayDataWrapper [mgl_MultiTexCoord,index -1,location 1,isVertexAttribute true] ,dataType 0x1406,bufferClazz类java.nio.FloatBuffer,元素4,组件2,stride 20b 5c,mappedElementCount 0,缓冲区java.nio.DirectFloatBufferU [pos = 0 lim = 20 cap = 40],vboEnabled true,vboName 1,vboUsage 0x88e4,vboTarget 0x8892,vboOffset 12,alive true]):GL_INVALID_OPERATION(1282 0x502),

我认为glVertexAttribPointer()的最后一个参数(0和Buffers.SIZEOF_FLOAT * 3)是可疑的,但我无法纠正它。

我的试验:

  1. 将变量arg0更改为0。
  2. 将变量stride更改为0.
  3. 将变量stride更改为0,将arg0更改为0.
  4. 而且我不确定我是否可以同时使用VAO和glDrawArraysInstanced方法。

    有什么建议吗?

    package demos.triangle;
    
    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import java.nio.FloatBuffer;
    
    import javax.media.opengl.DebugGL3;
    import javax.media.opengl.GL3;
    import javax.media.opengl.GLAutoDrawable;
    import javax.media.opengl.GLCapabilities;
    import javax.media.opengl.GLEventListener;
    import javax.media.opengl.GLProfile;
    import javax.media.opengl.awt.GLJPanel;
    import javax.media.opengl.fixedfunc.GLMatrixFunc;
    import javax.swing.JFrame;
    import javax.swing.SwingUtilities;
    
    import com.jogamp.common.nio.Buffers;
    import com.jogamp.opengl.util.FPSAnimator;
    import com.jogamp.opengl.util.PMVMatrix;
    
    public class MultTriangleVAOInstancedExperiment implements GLEventListener {
        private final JFrame frame;
        private final FPSAnimator animator;
        private final GLJPanel panel;
        private final Dimension dim = new Dimension(1024, 768);
        private double t0 = System.currentTimeMillis();
        private float theta;
    
        private int shaderProgram;
        private int vertShader;
        private int fragShader;
        private int modelViewProjectionMatrixLocation;
        private int transformMatrixLocation;
    
        private static final int locPos = 1;
        private static final int locCol = 2;
        private static final boolean useVao = false;
    //  private static final boolean useVao = true;
    
        private int[] vbo;
        private int[] vao;
    
        public static void main(String[] s){
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new MultTriangleVAOInstancedExperiment();
                }
            });
        }
    
        public MultTriangleVAOInstancedExperiment() {
            frame = new JFrame(this.getClass().getSimpleName());
            frame.setLayout(new BorderLayout());
            frame.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    animator.stop();
                    System.exit(0);
                }
            });
    
            GLProfile profile = GLProfile.get(GLProfile.GL3);
                panel = new GLJPanel(new GLCapabilities(profile));
            panel.addGLEventListener(this);
            panel.setPreferredSize(dim);
            frame.add(panel, BorderLayout.CENTER);
            frame.pack();
            frame.setVisible(true);
            animator = new FPSAnimator(panel, 60, true);
            animator.start();
        }
    
        @Override
        public void init(GLAutoDrawable drawable) {
            GL3 gl = drawable.getGL().getGL3();
            drawable.setGL(new DebugGL3(gl));
    
            gl.glClearColor(1, 1, 1, 1);
            gl.glClearDepth(1.0f);
    
            System.err.println("Chosen GLCapabilities: " + drawable.getChosenGLCapabilities());
            System.err.println("INIT GL IS: " + gl.getClass().getName());
            System.err.println("GL_VENDOR: " + gl.glGetString(GL3.GL_VENDOR));
            System.err.println("GL_RENDERER: " + gl.glGetString(GL3.GL_RENDERER));
            System.err.println("GL_VERSION: " + gl.glGetString(GL3.GL_VERSION));
    
            vertShader = gl.glCreateShader(GL3.GL_VERTEX_SHADER);
            fragShader = gl.glCreateShader(GL3.GL_FRAGMENT_SHADER);
    
            String[] vlines = new String[] { vertexShaderString };
            int[] vlengths = new int[] { vlines[0].length() };
            gl.glShaderSource(vertShader, vlines.length, vlines, vlengths, 0);
            gl.glCompileShader(vertShader);
    
            int[] compiled = new int[1];
            gl.glGetShaderiv(vertShader, GL3.GL_COMPILE_STATUS, compiled, 0);
            if(compiled[0] != 0) {
                System.out.println("Vertex shader compiled");
            } else {
                int[] logLength = new int[1];
                gl.glGetShaderiv(vertShader, GL3.GL_INFO_LOG_LENGTH, logLength, 0);
    
                byte[] log = new byte[logLength[0]];
                gl.glGetShaderInfoLog(vertShader, logLength[0], (int[])null, 0, log, 0);
    
                System.err.println("Error compiling the vertex shader: " + new String(log));
                System.exit(1);
            }
    
            String[] flines = new String[] { fragmentShaderString };
            int[] flengths = new int[] { flines[0].length() };
            gl.glShaderSource(fragShader, flines.length, flines, flengths, 0);
            gl.glCompileShader(fragShader);
    
            gl.glGetShaderiv(fragShader, GL3.GL_COMPILE_STATUS, compiled, 0);
            if(compiled[0] != 0){
                System.out.println("Fragment shader compiled.");
            } else {
                int[] logLength = new int[1];
                gl.glGetShaderiv(fragShader, GL3.GL_INFO_LOG_LENGTH, logLength, 0);
    
                byte[] log = new byte[logLength[0]];
                gl.glGetShaderInfoLog(fragShader, logLength[0], (int[])null, 0, log, 0);
    
                System.err.println("Error compiling the fragment shader: " + new String(log));
                System.exit(1);
            }
    
            shaderProgram = gl.glCreateProgram();
            gl.glAttachShader(shaderProgram, vertShader);
            gl.glAttachShader(shaderProgram, fragShader);
    
            gl.glBindAttribLocation(shaderProgram, locPos, "VertexPosition");
            gl.glBindAttribLocation(shaderProgram, locCol, "VertexColor");
    
            gl.glLinkProgram(shaderProgram);
    
            modelViewProjectionMatrixLocation = gl.glGetUniformLocation(shaderProgram, "uniform_Projection");
            System.out.println("modelViewProjectionMatrixLocation:" + modelViewProjectionMatrixLocation);
            transformMatrixLocation = gl.glGetUniformLocation(shaderProgram, "uniform_Transform");
            System.out.println("transformMatrixLocation:" + transformMatrixLocation);
    
            FloatBuffer interleavedBuffer = Buffers.newDirectFloatBuffer(vertices.length + colors.length);
            for(int i = 0; i < vertices.length/3; i++) {
                for(int j = 0; j < 3; j++) {
                    interleavedBuffer.put(vertices[i*3 + j]);
                }
                for(int j = 0; j < 4; j++) {
                    interleavedBuffer.put(colors[i*4 + j]);
                }
            }
            interleavedBuffer.flip();
    
            vao = new int[1];
            gl.glGenVertexArrays(1, vao , 0); // was 2
            gl.glBindVertexArray(vao[0]);
            vbo = new int[1];
            gl.glGenBuffers(1, vbo, 0); //was 2
            gl.glBindBuffer(GL3.GL_ARRAY_BUFFER, vbo[0]);
            gl.glBufferData(GL3.GL_ARRAY_BUFFER, interleavedBuffer.limit() * Buffers.SIZEOF_FLOAT, interleavedBuffer, GL3.GL_STATIC_DRAW);
    
            gl.glEnableVertexAttribArray(locPos);
            gl.glEnableVertexAttribArray(locCol);
    
                // 
            int stride = Buffers.SIZEOF_FLOAT * (3+4);
    
            long arg0 = Buffers.SIZEOF_FLOAT * 3;
    
                //suspicious 
            gl.glVertexAttribPointer( locPos, 3, GL3.GL_FLOAT, false, stride, 0);
            gl.glVertexAttribPointer( locCol, 4, GL3.GL_FLOAT, false, stride, arg0); 
    
            if(!useVao) { //added
              gl.glDisableVertexAttribArray(locPos);
              gl.glDisableVertexAttribArray(locCol);
            }
        }
    
        @Override
        public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
            System.out.println("Window resized to width=" + width + " height=" + height);
            GL3 gl = drawable.getGL().getGL3();
            gl.glViewport(0, 0, width, height);
        }
    
        @Override
        public void display(GLAutoDrawable drawable) {
            double t1 = System.currentTimeMillis();
            theta += (t1-t0)*0.005f;
            t0 = t1;
    
            GL3 gl = drawable.getGL().getGL3();
            gl.glClear(GL3.GL_COLOR_BUFFER_BIT | GL3.GL_DEPTH_BUFFER_BIT);
    
            gl.glUseProgram(shaderProgram);
    
            float[] instanceTransform0 = new float[16];
            float[] instanceTransform1 = new float[16];
            //I use PMVMatrix class in order to calculate model-view matrix.
            PMVMatrix mat0 = new PMVMatrix();
            mat0.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
            mat0.glLoadIdentity();
            mat0.glTranslatef(0.25f, 0f, 0f);
            mat0.glRotatef(15f*theta, 0.0f, 0.0f, 1.0f);
            mat0.glScalef(0.8f, 0.8f, 1f);
            mat0.glGetFloatv(GLMatrixFunc.GL_MODELVIEW, instanceTransform0, 0);
    
            PMVMatrix mat1 = new PMVMatrix();
            mat1.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
            mat1.glLoadIdentity();
            mat1.glTranslatef(-0.25f, 0f, 0f);
            mat1.glRotatef(10f*theta, 0.0f, 0.0f, 1.0f);
            mat1.glScalef(0.5f, 0.5f, 1f);
            mat1.glGetFloatv(GLMatrixFunc.GL_MODELVIEW, instanceTransform1, 0);
    
            //concatnate 2 float arrays.
            float[] instanceTransformConcatnated = concatnateArrays(instanceTransform0, instanceTransform1);
    
            gl.glUniformMatrix4fv(transformMatrixLocation, instanceTransformConcatnated.length, false, instanceTransformConcatnated , 0);
    
            if(useVao) {
                gl.glBindVertexArray(vao[0]);
            } else {
                gl.glEnableVertexAttribArray(locPos);
                gl.glEnableVertexAttribArray(locCol);
            }
            gl.glDrawArraysInstanced(GL3.GL_TRIANGLES, 0, 3, 2);
            if(useVao) {
                //EDIT: after removing the next line, the exception disappears.
                //gl.glBindVertexArray(0);
            } else {
                gl.glDisableVertexAttribArray(locPos);
                gl.glDisableVertexAttribArray(locCol);
            }
            gl.glUseProgram(0);
        }
    
        @Override
        public void dispose(GLAutoDrawable drawable){
            GL3 gl = drawable.getGL().getGL3();
            gl.glUseProgram(0);
            gl.glDeleteBuffers(2, vbo, 0);
            gl.glDetachShader(shaderProgram, vertShader);
            gl.glDeleteShader(vertShader);
            gl.glDetachShader(shaderProgram, fragShader);
            gl.glDeleteShader(fragShader);
            gl.glDeleteProgram(shaderProgram);
        }
    
        private float[] concatnateArrays(float[] arg0, float[] arg1) {
            float[] result = new float[arg0.length + arg1.length];
            System.arraycopy(arg0, 0, result, 0, arg0.length);
            System.arraycopy(arg1, 0, result, arg0.length, arg1.length);
            return result;
        }
    
        private final String vertexShaderString =
                "#version 330 \n" +
                        "\n" +
                        "uniform mat4 uniform_Projection; \n" + //not used
                        "uniform mat4 uniform_Transform[2]; \n" +
                        "in vec4  VertexPosition; \n" +
                        "in vec4  VertexColor; \n" +
                        "out vec4 tmpColor; \n" +
                        "void main(void) \n" +
                        "{ \n" +
                        "  tmpColor = VertexColor; \n" +
                        //"  gl_Position = uniform_Projection * VertexPosition; \n" +
                        "  gl_Position = uniform_Transform[gl_InstanceID] * VertexPosition; \n" +
                        "} ";
    
        private final String fragmentShaderString =
                "#version 330\n" +
                        "\n" +
                        "in vec4    tmpColor; \n" +
                        "out vec4   outColor; \n" +
                        "void main (void) \n" +
                        "{ \n" +
                        "  outColor = tmpColor; \n" +
                        "} ";
    
        private final float[] vertices = {
                1.0f, 0.0f, 0,
                -0.5f, 0.866f, 0,
                -0.5f, -0.866f, 0
        };
    
        private final float[] colors = {
                1.0f, 0.0f, 0.0f, 1.0f,
                0.0f, 1.0f, 0.0f, 1.0f,
                0f, 0f, 1.0f, 1f
        };
    
    }
    

1 个答案:

答案 0 :(得分:1)

我不清楚具体的异常消息,但是您肯定有一个问题:在init()方法的末尾,您为两个顶点属性调用glDisableVertexAttribArray()。此时,您的VAO受到约束。属性启用/禁用状态是VAO状态的一部分。因此,当您稍后在glBindVertexArray()方法中调用display()时,顶点属性将被禁用,您可以在没有任何已启用属性的情况下进行glDrawArraysInstanced()调用。

要解决此问题,您应该在glDisableVertexAttribArray()条件结束时进行init()次调用:

if (!useVao) {
    gl.glDisableVertexAttribArray(locPos);
    gl.glDisableVertexAttribArray(locCol);
}