Three.js Update Texture image

shaqb4 picture shaqb4 · Aug 26, 2013 · Viewed 26.2k times · Source

I'm using three.js to create a minecraft texture editor, similar to this. I'm just trying to get the basic click-and-paint functionality down, but I can't seem to figure it out. I currently have textures for each face of each cube and apply them by making shader materials with the following functions.

this.createBodyShaderTexture = function(part, update)
{
    sides = ['left', 'right', 'top', 'bottom', 'front', 'back'];
    images = [];
    for (i = 0; i < sides.length; i++)
    {
        images[i] = 'img/'+part+'/'+sides[i]+'.png'; 
    }
    texCube = new THREE.ImageUtils.loadTextureCube(images);
    texCube.magFilter = THREE.NearestFilter;
    texCube.minFilter = THREE.LinearMipMapLinearFilter;
    if (update)
    {
        texCube.needsUpdate = true;
        console.log(texCube);
    }
    return texCube;
}
this.createBodyShaderMaterial = function(part, update)
{

    shader = THREE.ShaderLib['cube'];
    shader.uniforms['tCube'].value = this.createBodyShaderTexture(part, update);
    shader.fragmentShader = document.getElementById("fshader").innerHTML;
    shader.vertexShader = document.getElementById("vshader").innerHTML;

    material = new THREE.ShaderMaterial({fragmentShader: shader.fragmentShader,  vertexShader: shader.vertexShader, uniforms: shader.uniforms});
    return material;
}

SkinApp.prototype.onClick = 
function(event)
{
    event.preventDefault();
        this.change(); //makes texture file a simple red square for testing
    this.avatar.remove(this.HEAD);

    this.HEAD = new THREE.Mesh(new THREE.CubeGeometry(8, 8, 8), this.createBodyShaderMaterial('head', false));
    this.HEAD.position.y = 10;
    this.avatar.add(this.HEAD);
    this.HEAD.material.needsUpdate = true;
        this.HEAD.dynamic = true;
}


Then, when the user clicks any where on the mesh, the texture file itself is update using canvas. The update occurs, but the change isn't showing up in the browser unless the page is refreshed. I've found plenty of examples of how to change the texture image to a new file, but not on how to show changes in the same texture file during runtime, or even if it's possible. Is this possible, and if not what alternatives are there?

Answer

Jos Dirksen picture Jos Dirksen · Aug 27, 2013

When you update a texture, whether its based on canvas, video or loaded externally, you need to set the following property on the texture to true:

If an object is created like this:

var canvas = document.createElement("canvas");
var canvasMap = new THREE.Texture(canvas)
var mat = new THREE.MeshPhongMaterial();
mat.map = canvasMap;
var mesh = new THREE.Mesh(geom,mat);

After the texture has been changed, set the following to true:

cube.material.map.needsUpdate = true;

And next time you render the scene it'll show the new texture.