Multiple objects in webgl

javascript, webgl

Solution

This code

gl.vertexAttribPointer(this.program.vertexPosAttrib, this.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(this.program.vertexPosAttrib);

Need to be called when drawing each mesh and not where it's called now. Additionally before calling `gl.vertexAttribPointer` for `this.program.vertexPosAttrib` you need to call

gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.vertexPosition);

Because `gl.vertexAttribPointer` binds the buffer currently bound to `gl.ARRAY_BUFFER` to the specified attribute.

In other words

gl.bindBuffer(gl.ARRAY_BUFFER, mesh.buffers.vertexPosition);
gl.vertexAttribPointer(mesh.program.vertexPosAttrib, mesh.itemSize, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(mesh.program.vertexPosAttrib);

Problem

I'm trying to render a few objects to a canvas and I'm having a bit of trouble understanding what's not working. I'm building two objects at the moment that represent the two meshes that I want to render. If I create one mesh the code works fine so the problem, I think, is that the data gets screwed up when I'm building two or more. Here's an example of the mesh data: ``` "name":"cone", "buffers":{ "vertexPosition":{}, // Buffer "vertexIndex":{} // Buffer }, "mesh":{ "vertices":[], // emptied it to fit on page "faces":[] // emptied it to fit on page }, "mvMatrix": Float32Array[16], "itemSize":3, "numItems":12, "program":{ "vertexPosAttrib":0, "mvMatrixUniform":{}, "pMatrixUniform":{} } ``` This is build from this function: ``` buildMeshData: function(){ this.mvMatrix = mat4.create(); this.buffers.vertexPosition = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.buffers.vertexPosition); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this.mesh.vertices), gl.STATIC_DRAW); this.buffers.vertexIndex = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.buffers.vertexIndex); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(this.mesh.faces), gl.STATIC_DRAW); this.itemSize = 3; this.numItems = this.mesh.faces.length; var vertexProps = { attributes: ['vec3', 'VertexPosition'], uniforms: ['mat4', 'MVMatrix', 'mat4', 'PMatrix'], varyings: ['vec3', 'TexCoord'] } var vertexShaderFunction = 'vTexCoord = aVertexPosition + 0.5; gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1);'; var vshaderInput = utils.buildVertexShader(vertexProps, vertexShaderFunction); var fragmentProps = { attributes: [], uniforms: [], varyings: ['vec3', 'TexCoord'] } var fragmentShaderFunction = 'gl_FragColor = vec4(vTexCoord, 1);'; var fshaderInput = utils.buildFragmentShader(fragmentProps, fragmentShaderFunction); this.program = gl.createProgram(); var vshader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vshader, vshaderInput); gl.compileShader(vshader); var fshader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fshader, fshaderInput); gl.compileShader(fshader); gl.attachShader(this.program, vshader); gl.attachShader(this.program, fshader); gl.linkProgram(this.program); gl.useProgram(this.program); this.program.vertexPosAttrib = gl.getAttribLocation(this.program, 'aVertexPosition'); gl.vertexAttribPointer(this.program.vertexPosAttrib, this.itemSize, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(this.program.vertexPosAttrib); this.program.mvMatrixUniform = gl.getUniformLocation(this.program, "uMVMatrix"); this.program.pMatrixUniform = gl.getUniformLocation(this.program, "uPMatrix"); scene.add(this); } ``` and the render function goes like this: ``` function render(){ currentTime = new Date().getTime(); deltaTime = (currentTime - initialTime) / 1000; // in seconds gl.viewport(0, 0, stage.width, stage.height); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); for(var i in scene.meshes){ (function(mesh){ mat4.translate(mesh.mvMatrix, mesh.mvMatrix, [0, 2 * i, -10 - (10 * i)]); gl.useProgram(mesh.program); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh.buffers.vertexIndex); gl.vertexAttribPointer(mesh.program.vertexPosAttrib, mesh.itemSize, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(mesh.program.vertexPosAttrib); gl.uniformMatrix4fv(mesh.program.mvMatrixUniform, false, mesh.mvMatrix); gl.uniformMatrix4fv(mesh.program.pMatrixUniform, false, scene.pMatrix); gl.drawElements(gl.TRIANGLES, mesh.numItems, gl.UNSIGNED_SHORT, 0); gl.disableVertexAttribArray(mesh.program.vertexPosAttrib); })(scene.meshes[i]) } // requestAnimationFrame(render); } ``` The result of this is the second object is drawn correctly but the first causes the error: ``` [.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 0 ``` ...and is therefore not drawn. Any ideas where the problem lies. Hopefully thats enough information from the code, I didn't want to put up too much, but if you need to see anything else I'll update.

Original source