【问题标题】:In WebGL, how can I load a 3D model (wavefront) that uses multiple textures?在 WebGL 中,如何加载使用多个纹理的 3D 模型(波前)?
【发布时间】:2012-12-19 16:12:45
【问题描述】:

到目前为止,我的代码支持加载 .obj(波前)文件并将其转换为 WebGL 对象(GL 缓冲区和渲染函数)。但是,我现在只能将一个纹理映射到整个对象。

我的文件加载器逐行读取,目前忽略 .obj 文件的 usemtl 行。我的对象渲染函数看起来像这样(改编自 http://learningwebgl.com/blog/?page_id=1217 教程)- 还不完美,但为了完整起见,我发布了整个工作函数:

this.render = function(gl){
    // push identity to the matrix stack (to apply changes only to this object)
    mvPushMatrix();

    // apply translations
    mat4.translate(mvMatrix, [this.transX, this.transY, this.transZ]);

    // apply scaling
    mat4.scale(mvMatrix, [this.scaleX, this.scaleY, this.scaleZ]);

    // apply rotations
    mat4.rotate(mvMatrix, this.rotX, [1, 0, 0]);
    mat4.rotate(mvMatrix, this.rotY, [0, 1, 0]);
    mat4.rotate(mvMatrix, this.rotZ, [0, 0, 1]);

    // load position buffer
    gl.bindBuffer(gl.ARRAY_BUFFER, this.positionVertexBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
        this.positionVertexBuffer.itemSize, gl.FLOAT, false, 0, 0);

    // load normals buffer
    gl.bindBuffer(gl.ARRAY_BUFFER, this.normalVertexBuffer);
    gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute,
        this.normalVertexBuffer.itemSize, gl.FLOAT, false, 0, 0);

    // load texture buffer
    gl.bindBuffer(gl.ARRAY_BUFFER, this.textureVertexBuffer);
    gl.vertexAttribPointer(shaderProgram.textureCoordAttribute,
        this.textureVertexBuffer.itemSize, gl.FLOAT, false, 0, 0);

    // load and apply the texture
    gl.activeTexture(gl.TEXTURE0);
    gl.bindTexture(gl.TEXTURE_2D, this.texture);
    gl.uniform1i(shaderProgram.samplerUniform, 0);

    // if blending is turned on, apply the blending and alpha value
    if(this.blending || this.firstRun){
        gl.blendFunc(gl.SRC_ALPHA, gl.ONE);
        gl.enable(gl.BLEND);
        gl.disable(gl.DEPTH_TEST);
        gl.uniform1f(shaderProgram.alphaUniform, this.alpha);
    }
    // otherwise, disable blending mode and render normally
    else{
        gl.disable(gl.BLEND);
        gl.enable(gl.DEPTH_TEST);
        gl.uniform1f(shaderProgram.alphaUniform, 1.0);
    }

    // render with indices IF indices are enabled
    if(this.indicesEnabled){
        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexVertexBuffer);
        setMatrixUniforms();
        gl.drawElements(gl.TRIANGLES,
            this.indexVertexBuffer.numItems, gl.UNSIGNED_SHORT, 0);
    }
    // otherwise, render normally
    else {
        setMatrixUniforms();
        gl.drawArrays(gl.TRIANGLES, 0, this.textureVertexBuffer.numItems);
    }

    // pop the matrix stack
    mvPopMatrix();

    // unflag first run after first frame rendering
    this.firstRun = false;
}

我想做的是读取使用多个纹理的文件。我怎样才能做到这一点?我最初的假设是从 .obj 中读取一个纹理的所有面,一旦纹理发生变化,就开始读取一个单独的缓冲区,然后将对象拆分为多个部分(每个纹理一个部分)并将它们渲染为如果它们是单独的对象。但在我更改代码之前,我想看看这是否正确,或者是否有解决这个问题的特别好的方法?

说实话,我根本不知道该怎么做。有什么建议?谢谢。

【问题讨论】:

    标签: javascript graphics html5-canvas webgl


    【解决方案1】:

    是的,这就是它的完成方式。

    通常对于专业游戏,艺术家需要为每个对象使用 1 个纹理,因为两个 100 多边形模型对 gl.drawXXX 的 2 次调用比一个 200 多边形模型对 gl.drawXXX 的 1 次调用慢。

    否则,一些团队有工具可以读取文件并将所有内容转换为 1 个纹理,将纹理合并为一个超级纹理。其他团队拥有将多边形分类为每个纹理 1 个模型的工具。

    他们有效地为每个多边形找出它属于哪个纹理,然后他们将这些顶点放入该纹理的存储桶中。最后他们写出每个桶,每个纹理 1 个。

    【讨论】:

    • 谢谢!我最终通过坚持使用一个纹理缓冲区来使其工作,但使用渲染函数的偏移索引和该缓冲区段的长度。相同的概念,但由于某种原因,它不适用于多个缓冲区,但此解决方案完美运行。
    猜你喜欢
    • 2016-08-22
    • 1970-01-01
    • 1970-01-01
    • 2012-06-24
    • 1970-01-01
    • 2016-06-22
    • 1970-01-01
    • 2019-07-09
    • 1970-01-01
    相关资源
    最近更新 更多