【问题标题】:GLTF index count same as buffer size errorGLTF 索引计数与缓冲区大小错误相同
【发布时间】:2019-01-04 16:02:00
【问题描述】:

我正在努力学习 WebGL,并且玩得很开心!我决定使用 glTF 作为这个项目的 3d 格式。我让它运行良好,有一个奇怪的例外。当索引计数较低时(比如一个简单的三角立方体),索引计数等于索引缓冲区大小。这不可能。在我拥有的所有其他模型中,索引计数是缓冲区大小的 1/2。

这些会导致渲染错误,例如“错误:WebGL 警告:drawElements:索引缓冲区太小。”。下面是相关代码。

可渲染构造函数:

constructor(type,indexCount,vertBuffer,indexBuffer,uvBuffer,normalBuffer,modelMatrix){
    this.type = type;
    this.indexCount = indexCount;

    this.name = "NONE";

    this.vertBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, this.vertBuffer);
    GL.bufferData(GL.ARRAY_BUFFER, vertBuffer, GL.STATIC_DRAW);
    GL.bindBuffer(GL.ARRAY_BUFFER, null);

    this.uvBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, this.uvBuffer);
    GL.bufferData(GL.ARRAY_BUFFER, uvBuffer, GL.STATIC_DRAW);
    GL.bindBuffer(GL.ARRAY_BUFFER, null);

    this.indexBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
    GL.bufferData(GL.ELEMENT_ARRAY_BUFFER, indexBuffer, GL.STATIC_DRAW);
    GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, null);

    this.normalBuffer = GL.createBuffer();
    GL.bindBuffer(GL.ARRAY_BUFFER, this.normalBuffer);
    GL.bufferData(GL.ARRAY_BUFFER, normalBuffer, GL.STATIC_DRAW);
    GL.bindBuffer(GL.ARRAY_BUFFER, null);

    this.matrix = modelMatrix;
    this.witMatrix = mat4.create();

    this.textures = [];

    //Create defaults
    this.setTexture(new dTexture(TEX.COLOR,"res/missingno.png"));
    this.setTexture(new dTexture(TEX.LIGHT,"res/rawLight.png"));
}

GLTF 到“可渲染”

static fromGLTF(type,gltf){
    console.log("GLTF: loading "+gltf.nodes[0].name);
    return new Renderable(type,
        gltf.nodes[0].mesh.primitives[0].indicesLength,
        gltf.nodes[0].mesh.primitives[0].attributes.POSITION.bufferView.data,
        gltf.accessors[gltf.nodes[0].mesh.primitives[0].indices].bufferView.data,
        gltf.nodes[0].mesh.primitives[0].attributes.TEXCOORD_0.bufferView.data,
        gltf.nodes[0].mesh.primitives[0].attributes.NORMAL.bufferView.data,
        gltf.nodes[0].matrix);
}

这里是渲染代码(不是很漂亮,但为了完整起见,这里是):

render(){
    GL.viewport(0.0,0.0,this.canvas.width,this.canvas.height);
    GL.clear(GL.COLOR_BUFFER_BIT | GL.DEPTH_BUFFER_BIT);

    this.renderables.forEach(renderable => {

        //mat4.identity(renderable.witMatrix);
        mat4.invert(renderable.witMatrix,renderable.matrix);
        mat4.transpose(renderable.witMatrix,renderable.witMatrix);

        GL.useProgram(this.programs[renderable.type].program);
        GL.uniformMatrix4fv(this.programs[renderable.type].pMatrix, false, this.projectionMatrix);
        GL.uniformMatrix4fv(this.programs[renderable.type].vMatrix, false, this.viewMatrix);
        GL.uniformMatrix4fv(this.programs[renderable.type].mMatrix, false, renderable.matrix);

        GL.enableVertexAttribArray(this.programs[renderable.type].positon);
        GL.bindBuffer(GL.ARRAY_BUFFER,renderable.vertBuffer);
        GL.vertexAttribPointer(this.programs[renderable.type].positon, 3, GL.FLOAT, false,0,0);

        GL.enableVertexAttribArray(this.programs[renderable.type].uv);
        GL.bindBuffer(GL.ARRAY_BUFFER,renderable.uvBuffer);
        GL.vertexAttribPointer(this.programs[renderable.type].uv, 2, GL.FLOAT, false,0,0);

        if(renderable.type == SHADER.STATIC){
            GL.uniform1i(this.programs[renderable.type].colorPos, 0);  // texture unit 0
            GL.activeTexture(GL.TEXTURE0);
            GL.bindTexture(GL.TEXTURE_2D, renderable.textures[TEX.COLOR].data);

            GL.uniform1i(this.programs[renderable.type].lightPos, 1);  // texture unit 1
            GL.activeTexture(GL.TEXTURE1);
            GL.bindTexture(GL.TEXTURE_2D, renderable.textures[TEX.LIGHT].data);
        }else if(renderable.type == SHADER.DYNAMIC){
            GL.uniform1i(this.programs[renderable.type].colorPos, 0);  // texture unit 0
            GL.activeTexture(GL.TEXTURE0);
            GL.bindTexture(GL.TEXTURE_2D, renderable.textures[TEX.COLOR].data);

            GL.enableVertexAttribArray(this.programs[renderable.type].normalPos);
            GL.bindBuffer(GL.ARRAY_BUFFER,renderable.normalBuffer);
            GL.vertexAttribPointer(this.programs[renderable.type].normalPos, 3, GL.FLOAT, false,0,0);

            GL.uniformMatrix4fv(this.programs[renderable.type].witMatrix, false, renderable.witMatrix);

            // set the light position
            GL.uniform3fv(this.programs[renderable.type].lightPosPos, [
                Math.sin(this.counter)*0.75,
                Math.cos(this.counter)*0.75+1,
                0
            ]);
            this.counter+=this.dt*0.25;
        }

        GL.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, renderable.indexBuffer);
        GL.drawElements(GL.TRIANGLES,renderable.indexCount,GL.UNSIGNED_SHORT,0);

        GL.activeTexture(GL.TEXTURE1);
        GL.bindTexture(GL.TEXTURE_2D,this.nullLightmap.data);
    });

    GL.flush();
}

有什么想法吗?

【问题讨论】:

  • “当索引计数较低时(比如简单的三角立方体),索引计数等于索引缓冲区大小。这不可能。在我拥有的所有其他模型中,索引计数是缓冲区大小的 1/2。" 我假设索引缓冲区的类型为GL.UNSIGNED_BYTE,当索引数量较少时,索引缓冲区的类型为GL.UNSIGNED_SHORT甚至GL.UNSIGNED_INT,如果有更多索引。它的类型是GL.UNSIGNED_BYTE 当然索引的数量等于缓冲区的大小(以字节为单位)。

标签: javascript webgl gltf


【解决方案1】:

当索引计数较低时(例如简单的三角立方体),索引计数等于索引缓冲区大小。这不可能。在我拥有的所有其他模型中,索引计数是缓冲区大小的 1/2。

索引缓冲区的大小取决于索引的数量和componentType
Accessor Element Size

componentType         Size in bytes
5120 (BYTE)           1
5121 (UNSIGNED_BYTE)  1
5122 (SHORT)          2
5123 (UNSIGNED_SHORT) 2
5125 (UNSIGNED_INT)   4
5126 (FLOAT)          4

componentType 指定单个索引的数据类型。当索引数较少时(UNSIGNED_BYTE,而索引缓冲区的类型为UNSIGNED_SHORT 甚至UNSIGNED_INT,如果有更多索引。如果类型是UNSIGNED_BYTE,那么索引的数量当然等于缓冲区的大小(以字节为单位)。

取决于您必须熟练使用绘图调用的元素索引的类型,例如GL.UNSIGNED_BYTE:

GL.drawElements(GL.TRIANGLES,renderable.indexCount,GL.UNSIGNED_BYTE,0); 

注意,componentType (5120, 5121, ...) 的值似乎是任意的,它们是 OpenGL 枚举器常量 GL.BYTE, GL.UNSIGNED_BYTE, ...

我建议将componentType 传递给constructor,就像您使用索引数量(indexCount)一样

constructor(
    type,indexCount,componentType,
    vertBuffer,indexBuffer,uvBuffer,normalBuffer,modelMatrix){

    this.indexCount    = indexCount;
    this.componentType = componentType;

并在绘制几何图形时使用它:

GL.drawElements(
    GL.TRIANGLES,
    renderable.indexCount,
    renderable.componentType,
    0);

【讨论】:

  • 就是这样!谢谢!现在我看到了,它在世界上都是有意义的。
猜你喜欢
  • 2015-11-01
  • 2016-02-22
  • 1970-01-01
  • 1970-01-01
  • 2018-09-19
  • 2021-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多