I am trying to create two meshes, a square and a triangle. The code is at the bottom.
I first create a shader program "program1", array buffer "vertexBuffer1" and an element array buffer "indexBuffer1" for the first mesh. The first mesh is a square.
Then I do the same thing for the second mesh. The second mesh is a triangle.
When I run the code I get the error:
[.Offscreen-For-WebGL-000002B76A973870]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 0
I don't get the error if I comment out this line:
//gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0); // <- problem!
I think what is happening is that somehow the triangle's vbo ("vertexBuffer2") gets connected to the square's shader program ("program1"). This causes
gl.drawElements(gl.TRIANGLES, indices1.length, gl.UNSIGNED_SHORT, 0);
to fail as it is trying to draw a square from the triangles vertex buffer.
I don't understand why
gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0); // <- problem!
causes "program1" to connect to "vertexBuffer2", if that is even the problem. How do I make theese two programs ("program1" and "program2") connect to each their buffers?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<canvas id="canvas" width="500" height="450" style="border:1px solid black"></canvas>
<script>
// setup gl
var canvas = document.getElementById("canvas");
var gl = canvas.getContext("webgl");
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clearColor(0.5, 0.5, 0.5, 0.9);
gl.clearDepth(1.0);
gl.viewport(0.0, 0.0, canvas.width, canvas.height);
// setup mesh 1
// // vertex shader
var vertexShader1 = gl.createShader(gl.VERTEX_SHADER);
var vertexShaderCode = `
// in
attribute vec3 position;
void main(void) {
gl_Position = vec4(position, 1.);
}
`;
gl.shaderSource(vertexShader1, vertexShaderCode);
gl.compileShader(vertexShader1);
// // fragment shader
var fragmentShader1 = gl.createShader(gl.FRAGMENT_SHADER);
var fragmentShaderCode = `
precision mediump float;
// in
void main(void) {
gl_FragColor = vec4(1., 0., 0., 1.);
}
`;
gl.shaderSource(fragmentShader1, fragmentShaderCode);
gl.compileShader(fragmentShader1);
// // program1
var program1 = gl.createProgram();
gl.attachShader(program1, vertexShader1);
gl.attachShader(program1, fragmentShader1);
gl.linkProgram(program1);
gl.useProgram(program1);
// // create buffer 1
var vertices1 = [ // suqare
-0.5, -0.5, 0,
0.5, -0.5, 0,
0.5, 0.5, 0,
-0.5, 0.5, 0,
];
var vertexBuffer1 = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer1);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices1), gl.STATIC_DRAW);
var loc = gl.getAttribLocation(program1, "position");
gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(loc);
var indices1 = [
0,1,2,
0,2,3,
];
var indexBuffer1 = gl.createBuffer ();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer1);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices1), gl.STATIC_DRAW);
// setup mesh 2
// // vertex shader
var vertexShader2 = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader2, vertexShaderCode); // uses same vertexShaderCode as above
gl.compileShader(vertexShader2);
// // fragment shader
var fragmentShader2 = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader2, fragmentShaderCode);
gl.compileShader(fragmentShader2);
// // program2
var program2 = gl.createProgram();
gl.attachShader(program2, vertexShader2);
gl.attachShader(program2, fragmentShader2);
gl.linkProgram(program2);
gl.useProgram(program2);
// // create buffer 2
var vertices2 = [ // triangle one less vertex than in buffer 1
-0.5, -0.5, 0,
0.5, -0.5, 0,
0.5, 0.5, 0,
];
var vertexBuffer2 = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer2);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices2), gl.STATIC_DRAW);
var loc = gl.getAttribLocation(program2, "position");
// On the line below it seems like program1 instead of program2 gets connected to the vertexBuffer2
gl.vertexAttribPointer(loc, 3, gl.FLOAT, false, 0, 0); // <- problem!
gl.enableVertexAttribArray(loc);
var indices2 = [
0,1,2,
];
var indexBuffer2 = gl.createBuffer ();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer2);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices2), gl.STATIC_DRAW);
// render
// // clear
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// // render mesh 1 (the square)
gl.useProgram(program1);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer1);
gl.drawElements(gl.TRIANGLES, indices1.length, gl.UNSIGNED_SHORT, 0); // <- this line fail
</script>
</body>
</html>