1
votes

As of now, my code supports loading an .obj (wavefront) file and translating it into a WebGL object (GL buffers and a render function). However, I can only map one texture to the entire object right now.

My file loader reads line by line, and currently ignores the usemtl lines of the .obj files. My object render function looks like this (adapted from the http://learningwebgl.com/blog/?page_id=1217 tutorials) - not perfect yet, but for the sake of completeness I posted the whole working function:

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;
}

What I would like to do is read in files that use multiple textures. How can I do this? My initial assumption is to read in all of the faces of one texture from the .obj, and once the texture changes, start reading a separate buffer, and then just split the object into multiple pieces (one piece per texture) and render them as if they were separate objects. But before I change my code, I wanted to see if this was correct, or if there is a particularly good way of approaching this issue?

To be honest, I'm not sure how to go about this at all. Any suggestions? Thank you.

1

1 Answers

2
votes

Yes, That's pretty much the way it's done.

Usually for professional games, artists will be required to use 1 texture per object because 2 calls to gl.drawXXX for two 100 polygon models is slower than 1 call to gl.drawXXX for one 200 polygon model.

Otherwise, some teams have tools that will read a file and convert everything to 1 texture, merging the textures into one super texture. Other teams have tools that sort the polygons into 1 model per texture.

Effectively for each polygon they figure out what texture it belongs to, then they put those vertices in a bucket for that texture. Finally they write out each bucket, 1 for each texture.