Opengl es WebGL:添加纹理导致抽屉元素错误(属性缓冲区空间不足)

Opengl es WebGL:添加纹理导致抽屉元素错误(属性缓冲区空间不足),opengl-es,webgl,texture2d,Opengl Es,Webgl,Texture2d,我想从model.json文件中绘制一个三维模型(例如房子)。我用蓝色这样的单色画房子没有问题。但是,当我尝试使用纹理而不是颜色时,我收到一个错误: WebGL:抽屉元素:绑定顶点属性缓冲区没有 绑定元素数组中给定索引的足够大小 我搜索过网络,尝试过数百种不同的修改,但我根本无法克服这个错误——我对WebGL不够精通,看不出哪里出了问题。有一个包含多个纹理图像的图像文件夹,但在这一点上,如果我能为整个房子绘制一个纹理,我会欣喜若狂 问题在于renderable.js(附件),但您可以同时访问所有

我想从model.json文件中绘制一个三维模型(例如房子)。我用蓝色这样的单色画房子没有问题。但是,当我尝试使用纹理而不是颜色时,我收到一个错误:

WebGL:抽屉元素:绑定顶点属性缓冲区没有 绑定元素数组中给定索引的足够大小

我搜索过网络,尝试过数百种不同的修改,但我根本无法克服这个错误——我对WebGL不够精通,看不出哪里出了问题。有一个包含多个纹理图像的图像文件夹,但在这一点上,如果我能为整个房子绘制一个纹理,我会欣喜若狂

问题在于renderable.js(附件),但您可以同时访问所有文件。任何帮助都将不胜感激,我不知道还能去哪里

renderable.js

    "use strict";
function RenderableModel(gl,model){
    function Drawable(attribLocations, vArrays, nVertices, indexArray, drawMode){
      // Create a buffer object
      var vertexBuffers=[];
      var nElements=[];
      var nAttributes = attribLocations.length;

      for (var i=0; i<nAttributes; i++){
          if (vArrays[i]){
              vertexBuffers[i] = gl.createBuffer();
              if (!vertexBuffers[i]) {
                console.log('Failed to create the buffer object');
                return null;
              }
              // Bind the buffer object to an ARRAY_BUFFER target

              gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffers[i]);
              // Write date into the buffer object
              gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vArrays[i]), gl.STATIC_DRAW);
              // Texture coords must always be passed as last attribute location (a_Attribute)
              nElements[i] = (i == (nAttributes - 1))? 2: vArrays[i].length/nVertices;
          }
          else{
              vertexBuffers[i]=null;
          }
      }

      var indexBuffer=null;
      if (indexArray){
        indexBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexArray), gl.STATIC_DRAW);
      }

      var a_texture = createTexture("texture0.jpg");
      // Set the texture unit 0 to the sampler
      gl.activeTexture(gl.TEXTURE0);
      gl.bindTexture(gl.TEXTURE_2D, a_texture);

      this.draw = function (){
        nElements[1] = 2;
        for (var i=0; i<nAttributes; i++){
          if (vertexBuffers[i]){
              gl.enableVertexAttribArray(attribLocations[i]);
              // Bind the buffer object to target
              gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffers[i]);
              // Assign the buffer object to a_Position variable
              gl.vertexAttribPointer(attribLocations[i], nElements[i], gl.FLOAT, false, 24, 0);
          }
          else{
              gl.disableVertexAttribArray(attribLocations[i]); 
              gl.vertexAttrib3f(attribLocations[i],1,1,1);
              //console.log("Missing "+attribLocations[i])
          }
        }

        if (indexBuffer){
            gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
            gl.drawElements(drawMode, indexArray.length, gl.UNSIGNED_SHORT, 0);
        }
        else{
            gl.drawArrays(drawMode, 0, nVertices);
        }
      }
    }

    // Vertex shader program
    var VSHADER_SOURCE =
      'attribute vec2 textureCoord;\n' +    
      'attribute vec3 position;\n' +

      'uniform mat4 modelT, viewT, projT;\n'+

      //'varying vec4 v_Color;\n' +
      'varying highp vec2 vTextureCoord;\n' +
      'void main() {\n' +
      '  gl_Position = projT*viewT*modelT*vec4(position,1.0);\n' +
      //'  v_Color = vec4(0, 1.0, 0.0, 1.0);\n' +   // use instead of textures for now
      '  vTextureCoord = textureCoord;\n' +
      '}\n';


    // Fragment shader program
    var FSHADER_SOURCE =
      '#ifdef GL_ES\n' +
      'precision highp float;\n' +
      '#endif\n' +

      'uniform sampler2D uSampler;\n' +
      //'varying vec4 v_Color;\n' + // use instead of texture
      'varying highp vec2 vTextureCoord;\n' +
      'void main() {\n' +  
      // 'vec4 v_Color = vec4(texture2D(uSampler, vTextureCoord).rgb, 1.0);\n'+
      '  gl_FragColor = texture2D(uSampler, vTextureCoord);\n' +
      '}\n';


    // create program
    var program = createProgram(gl, VSHADER_SOURCE, FSHADER_SOURCE);
    if (!program) {
        console.log('Failed to create program');
        return false;
    }

    var a_Position = gl.getAttribLocation(program, 'position');       
    var a_TextureCoord = gl.getAttribLocation(program, 'textureCoord'); // for texture
    var a_Locations = [a_Position,a_TextureCoord];

    // Get the location/address of the uniform variable inside the shader program.
    var mmLoc = gl.getUniformLocation(program,"modelT");
    var vmLoc = gl.getUniformLocation(program,"viewT");
    var pmLoc = gl.getUniformLocation(program,"projT");
    // textures
    var textureLoc = gl.getUniformLocation(program,'uSampler');

    var drawables=[];
    var modelTransformations=[];
    var nDrawables=0;
    var nNodes = (model.nodes)? model.nodes.length:1;
    var drawMode=(model.drawMode)?gl[model.drawMode]:gl.TRIANGLES;

    for (var i= 0; i<nNodes; i++){
        var nMeshes = (model.nodes)?(model.nodes[i].meshIndices.length):(model.meshes.length);
        for (var j=0; j<nMeshes;j++){
            var index = (model.nodes)?model.nodes[i].meshIndices[j]:j;
            var mesh = model.meshes[index];
            drawables[nDrawables] = new Drawable(
                a_Locations,[mesh.vertexPositions, mesh.vertexTexCoordinates],
                mesh.vertexPositions.length/3,
                mesh.indices, drawMode
            );

            var m = new Matrix4();
            if (model.nodes)
                m.elements=new Float32Array(model.nodes[i].modelMatrix);
            modelTransformations[nDrawables] = m;

            nDrawables++;
        }
    }
    // Get the location/address of the vertex attribute inside the shader program.
    this.draw = function (cameraPosition,pMatrix,vMatrix,mMatrix)
    {
        gl.useProgram(program);
        gl.uniformMatrix4fv(pmLoc, false, pMatrix.elements);
        gl.uniformMatrix4fv(vmLoc, false, vMatrix.elements);
        gl.uniform1i(textureLoc, 0);

        // pass variables determined at runtime
        for (var i= 0; i<nDrawables; i++){
            // pass model matrix
            var mMatrix=modelTransformations[i];
            gl.uniformMatrix4fv(mmLoc, false, mMatrix.elements);                        
            drawables[i].draw();
        }
        gl.useProgram(null);
    }




    this.getBounds=function() // Computes Model bounding box
    {       
        var xmin, xmax, ymin, ymax, zmin, zmax;
        var firstvertex = true;
        var nNodes = (model.nodes)?model.nodes.length:1;
        for (var k=0; k<nNodes; k++){
            var m = new Matrix4();
            if (model.nodes)m.elements=new Float32Array(model.nodes[k].modelMatrix);
            //console.log(model.nodes[k].modelMatrix);
            var nMeshes = (model.nodes)?model.nodes[k].meshIndices.length:model.meshes.length;
            for (var n = 0; n < nMeshes; n++){
                var index = (model.nodes)?model.nodes[k].meshIndices[n]:n;
                var mesh = model.meshes[index];
                for(var i=0;i<mesh.vertexPositions.length; i+=3){
                    var vertex = m.multiplyVector4(new Vector4([mesh.vertexPositions[i],mesh.vertexPositions[i+1],mesh.vertexPositions[i+2],1])).elements;
                    //if (i==0){
                    //  console.log([mesh.vertexPositions[i],mesh.vertexPositions[i+1],mesh.vertexPositions[i+2]]);
                    //  console.log([vertex[0], vertex[1], vertex[2]]);
                    //}
                    if (firstvertex){
                        xmin = xmax = vertex[0];
                        ymin = ymax = vertex[1];
                        zmin = zmax = vertex[2];
                        firstvertex = false;
                    }
                    else{
                        if (vertex[0] < xmin) xmin = vertex[0];
                        else if (vertex[0] > xmax) xmax = vertex[0];
                        if (vertex[1] < ymin) ymin = vertex[1];
                        else if (vertex[1] > ymax) ymax = vertex[1];
                        if (vertex[2] < zmin) zmin = vertex[2];
                        else if (vertex[2] > zmax) zmax = vertex[2];
                    }
                }
            }
        }
        var dim= {};
        dim.min = [xmin,ymin,zmin];
        dim.max = [xmax,ymax,zmax];
        //console.log(dim);
        return dim;
    }

    // Load texture image and create/return texture object
    function createTexture(imageFileName)
    {
        var tex = gl.createTexture();
        var img = new Image();
        img.onload = function(){
            gl.bindTexture(gl.TEXTURE_2D, tex);
            gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,true);
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
            gl.bindTexture(gl.TEXTURE_2D, null);
        }
        img.src = imageFileName;
        return tex;
    }
}
“严格使用”;
函数渲染模型(gl,模型){
可绘制的函数(AttriblLocations、varray、nVertices、indexArray、drawMode){
//创建缓冲区对象
var vertexBuffers=[];
变量元素=[];
var NatAttributes=attribLocations.length;

对于(var i=0;i而言,该错误意味着您的一个索引对于当前已连接的缓冲区来说太大

示例:假设您有一个包含3个位置的位置缓冲区

 [0.123, 0.010, 0.233,
  0.423, 0.312, 0.344,
  0.933, 1.332, 0.101]
现在,假设您创建了一个索引缓冲区

 [0, 1, 3]
您只有3个位置,因此唯一有效的索引是0、1和2。
3
超出范围。这是您得到的错误

一些可能性:

  • 你的数据可能不好。检查你的索引

  • 您绘制了一个顶点较少但属性较多的模型,然后绘制了另一个顶点较多但属性较少的模型。在绘制第二个模型时,上一个模型的属性保持打开状态

  • 换句话说

    // setup first model with only 3 vertices, both positions and colors.
    gl.enableVertexAttribArray(0);
    gl.bindBuffer(gl.BUFFER_ARRAY, bufferWith3Positions);
    gl.vertexAttribPointer(0, ....);
    gl.enableVertexAttribArray(1);
    gl.bindBuffer(gl.BUFFER_ARRAY, bufferWith3Colors);
    gl.vertexAttribPointer(1, ....);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesForFirstModel);
    
    // setup first model with 6 vertices but no colors
    gl.bindBuffer(gl.BUFFER_ARRAY, bufferWith6Positions);
    gl.vertexAttribPointer(0, ....);
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesForSecondModel);
    
    您将得到一个错误,因为attrib#1仍在使用3种颜色引用
    bufferWith3Colors
    。您需要关闭该属性

    gl.disableVertexAttribArray(1);
    

    注意:假设着色器仍在使用属性#1。如果不是,则即使
    bufferWith3Colors
    仍附加到属性#1,也不应出现错误。

    +1:但是,值得一提的是,此行为特定于WebGL,这是讨论的一个额外的安全功能。在OpenGL和OpenGL中,使用超出ra的索引nge是未定义的行为,即使使用调试输出扩展most驱动程序(我知道)发生这种情况时不会报告。如果我有足够的可信度,我会+1!非常感谢。我回去检查了每个属性数组的长度,注意到textureCoordinate数组是1。所以我查看模型文件,注意到我得到值的VertextTextureCoordinates是2D数组-我想这是因为模型文件正在考虑同一网格上可能存在多个纹理。谢谢gman。问题已解决。