Lauren Hughes
Lauren Hughes

Reputation: 43

What is causing invalid operation on my draw arrays call?

Using WebGL I am trying to draw a simple triangle from scratch.

I have experience writing openGL applications in C++, and have looked at the webGL reference card to translate my code.

However, I am having difficulty debugging the application. The particular error message I am getting is:

GL ERROR :GL_INVALID_OPERATION : glDrawArrays: attempt to access out of range vertices in attribute 0

The entire code is here: https://github.com/gheshu/webGL_experiments

The vertex data is laid out as 3 vectors of 3 floats. Three attributes exist: position, normal, and color, and should be bound on indices 0, 1, 2.

some important snippets:

mesh class:

class Mesh{
    constructor(){
        this.num_vertices = 0;  
        this.vbo = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
        gl.enableVertexAttribArray(0);
        gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 4*3*3, 0);
        gl.enableVertexAttribArray(1);
        gl.vertexAttribPointer(1, 3, gl.FLOAT, false, 4*3*3, 4*3);
        gl.enableVertexAttribArray(2);
        gl.vertexAttribPointer(2, 3, gl.FLOAT, false, 4*3*3, 4*3*2);
    }
    upload(buffer){
        console.log(buffer);
        gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
        gl.bufferData(gl.ARRAY_BUFFER, buffer, gl.STATIC_DRAW);
        this.num_vertices = buffer.length / 9;
    }
    draw(){
        gl.bindBuffer(gl.ARRAY_BUFFER, this.vbo);
        gl.drawArrays(gl.TRIANGLES, 0, this.num_vertices);
    }
    destroy(){
        gl.deleteBuffer(this.vbo);
    }
}

program class:

class GLProgram{
    constructor(vertShader, fragShader){
        this.prog = gl.createProgram();
        gl.attachShader(this.prog, vertShader.id);
        gl.attachShader(this.prog, fragShader.id);
        gl.bindAttribLocation(this.prog, 0, "position");
        gl.bindAttribLocation(this.prog, 1, "normal");
        gl.bindAttribLocation(this.prog, 2, "color");
        gl.linkProgram(this.prog);
        var log = gl.getProgramInfoLog(this.prog);
        if(log.length){
            console.log();
        }
        gl.detachShader(this.prog, vertShader.id);
        vertShader.destroy();
        gl.detachShader(this.prog, fragShader.id);
        fragShader.destroy();
    }
    bind(){
        gl.useProgram(this.prog);
    }
    destroy(){
        gl.deleteProgram(this.prog);
    }
}

vertex shader:

attribute vec3 position; 
attribute vec3 normal; 
attribute vec3 color; 

varying vec3 vColor;

void main(){    
    gl_Position = vec4(position, 1.0);  
    vColor = color; 
}   

fragment shader:

precision mediump float;    

varying vec3 vColor;    

void main(){    
    gl_FragColor = vec4(vColor, 1.0);   
}

I would greatly appreciate any help or tips you may have in fixing this issue.

Upvotes: 2

Views: 304

Answers (1)

grovesNL
grovesNL

Reputation: 6075

At the bottom of your draw.js file, you destroy mesh and prog:

mesh.destroy();
prog.destroy();

In JavaScript window.requestAnimationFrame(onFrame); will actually invoke onFrame after those destroy methods are called. So by the time onFrame is executed both mesh and prog don't exist. I would recommend reading more about requestAnimationFrame so you can destroy these later (i.e. after your animation loop has stopped running).

You can verify the behavior just by removing those destroy lines and it will render fine.

Upvotes: 2

Related Questions