12
votes

I'm attempting to fix a pre-existing bug in some code that is based on THREE.js rev 49 with some custom shaders.

I'm a total WebGL newb, so I haven't been able to make much heads or tails of other answers since they seemed to assume a lot more knowledge than I had. I would be super appreciative of even any hints as to what to look for! :) The end result of the code is to draw a translucent box wireframe and paint the faces with translucent textures.

The particular error is:

[.WebGLRenderingContext]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 1

I traced the issue to a particular _gl.drawElements( _gl.TRIANGLES, geometryGroup.__webglFaceCount, _gl.UNSIGNED_SHORT, 0 ); in THREE.WebGLRenderer.renderBuffer.

Here is a snippet of the calling code:

scene.overrideMaterial = depthMaterial; // shaders below
var ctx = renderer.getContext(); // renderer is a THREE.WebGLRenderer
ctx.disable(ctx.BLEND);
// renderTarget is a THREE.WebGLRenderTarget, _camera, scene is obvious
renderer.render(scene, _camera, renderTarget, true); // error occurs here

Here are the relevant shaders:

    uniforms: {},

    vertexShader: [
        "varying vec3 vNormal;",

        "void main() {",

            "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
            "vNormal = normalMatrix * normal;",

            "gl_Position = projectionMatrix * mvPosition;",

        "}"
    ].join("\n"),

    fragmentShader: [
        "vec4 pack_depth( const in highp float depth ) {",

            "const highp vec4 bit_shift = vec4( 256.0, 256.0*256.0, 256.0*256.0*256.0, 256.0*256.0*256.0*256.0 );",
            "vec4 res = depth * bit_shift;",
            "res.x = min(res.x + 1.0, 255.0);",
            "res = fract(floor(res) / 256.0);",
            "return res;",

        "}",

        "void main() {",
            "gl_FragData[0] = pack_depth( gl_FragCoord.z );",
        "}"
    ].join("\n")

Thanks for your help!

2

2 Answers

25
votes

In WebGL you set up buffers full of data, usually vertex positions, normals, colors, texture coordinates. You then ask WebGL to draw something with those buffers. You can ask with gl.drawArrays or with gl.drawElements. gl.drawElements uses another buffer full of indices to decide which vertices to use.

The error you got means you asked WebGL to draw or access more elements than the buffers you setup. In other words, if you provide only 3 vertices worth of data but you ask it to draw 4 vertices when you call gl.drawArrays you'll get that error. Similarly if you only provide 3 vertices worth of data but then setup indices that access any vertex greater than 2 you'll get that error. You've got 3 vertices numbered #0, #1, and #2 so if any of your indices are greater than 2 you're asking WebGL to access something out of range of the 3 vertices you provided.

So, check your data. Are you indices out of range? Is one of your buffers shorter than the others? etc..

4
votes

I'm adding this for thoroughness - I was using an imported OBJ model and was getting this error when creating the shader via THREE.ShaderLib["normalmap"]

The fix was simply calling computeTangents() on the mesh's geometry object:

model.geometry.computeTangents();

archived the answer here