What is common cause of range out of bounds of buffer in WebGL

There are only 3 reasons you'd get that error when calling gl.drawElements

  1. Your indices are referencing vertices out of range of your buffers

    For example you make a buffer and put 3 position values in it

    var buf = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, buf);
    var data = [1,2,3,4,5,6,7,8,9]; // 3 (3 value) positions
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
    

    Since there are only 3 positions the only possible indices are 0, 1, and 2. So if you put ANY OTHER VALUE in your index buffer you'll get that error.

    var indexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
    var indices = [0,1,3]; // ERROR! That 3 is out of range
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
    
    // This will generate an out of bounds error because
    // the 3 index we put in the index buffer is out of range
    // as the only valid indices are 0, 1, and 2.
    gl.drawElements(gl.TRIANGLE, 3, gl.UNSIGNED_SHORT, 0);
    
  2. You tried to draw too many indices or set the offset out of range

    Given the setup above if you did

    gl.drawElements(gl.TRIANGLE, 4, gl.UNSIGNED_SHORT, 0); 
    

    You'd get out of range because you only put 3 indices in but you're asking to draw 4. Similarly if you change the offset

    gl.drawElements(gl.TRIANGLE, 3, gl.UNSIGNED_SHORT, 1);
    

    Again you only put 3 indices in but you're asking it to draw index 1,2, and 3 instead of 0, 1, and 2.

  3. You set your attributes to access too much data

    Let's assume we put in three 3 value positions like above. If we set the attribute to pull out three 4 value positions like this

    var size = 4; // ERROR! There are only 3 value per position
    gl.vertexAttribPointer(location, size, gl.FLOAT, false, 0, 0);
    

    That setup will try to access 12 floats of data (assuming your indices are correct) but you only put in 9 floats of data. size should equal 3

    You can similarly mess up if you set the stride or the offset (the last 2 parameters to gl.vertexAtrribPointer to the wrong values. Nearly all WebGL programs always use 0, 0 there. If you're doing something more fancy make sure you set them correctly.


It's possible you may not be passing your array as the correct type. It's easy to forget to cast your vertices or indices from a general Javascript array to an explicitly typed array.

For example (adapted from gman's first example):

var buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
var data = [1,2,3,  4,5,6,  7,8,9,  10,11,12];  // 4 3-D positions
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), gl.STATIC_DRAW);
//                             ^^^^^^^^^^^^^^^^
// Failure to explicitly construct a typed array here can give this WebGL error,
// if you bind this array to an attribute:
//   GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 0

var indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buf);
var indices = [3,2,1];
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
//                                     ^^^^^^^^^^^^^^^
// Failure to explicitly construct a typed array here gives this WebGL error:
//   GL_INVALID_OPERATION : glDrawElements: range out of bounds for buffer

gl.drawElements(gl.TRIANGLE, 3, gl.UNSIGNED_SHORT, 0);

In Javascript, every numeric value is represented by default as an object of type Number, which is an IEEE 64-bit float under the hood. So, for example, the first element of the indices array, 3, is represented by these 64 bits:

0000 0000 0001 1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000

If you pass the regular Javascript array into the element array buffer, then when gl.drawElements() asks to interpret the buffer as unsigned shorts (16-bit ints), then it instead sees those first 64 bits as 4 groups of 16 bits, and reads out the following values:

0000 0000 0001 1000  =  24
0000 0000 0000 0000  =   0
0000 0000 0000 0000  =   0
0000 0000 0000 0000  =   0

And of course 24 is out of range for our 4-element vertex position array buffer.

Tags:

Webgl