11
votes

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?

2

2 Answers

20
votes

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.

4
votes

Here is all the basics of what you have to know about "updating" stuff in three.js: https://threejs.org/docs/#manual/introduction/How-to-update-things