Using textures in THREE.js

Andrea picture Andrea · Oct 27, 2011 · Viewed 104.9k times · Source

I am starting with THREE.js, and I am trying to draw a rectangle with a texture on it, lit by a single source of light. I think this is as simple as it gets (HTML omitted for brevity):

function loadScene() {
    var world = document.getElementById('world'),
        WIDTH = 1200,
        HEIGHT = 500,
        VIEW_ANGLE = 45,
        ASPECT = WIDTH / HEIGHT,
        NEAR = 0.1,
        FAR = 10000,

        renderer = new THREE.WebGLRenderer(),
        camera = new THREE.Camera(VIEW_ANGLE, ASPECT, NEAR, FAR),
        scene = new THREE.Scene(),
        texture = THREE.ImageUtils.loadTexture('crate.gif'),
        material = new THREE.MeshBasicMaterial({map: texture}),
        // material = new THREE.MeshPhongMaterial({color: 0xCC0000});
        geometry = new THREE.PlaneGeometry(100, 100),
        mesh = new THREE.Mesh(geometry, material),
        pointLight = new THREE.PointLight(0xFFFFFF);

    camera.position.z = 200;    
    renderer.setSize(WIDTH, HEIGHT);
    scene.addChild(mesh);
    world.appendChild(renderer.domElement);
    pointLight.position.x = 50;
    pointLight.position.y = 50;
    pointLight.position.z = 130;
    scene.addLight(pointLight); 
    renderer.render(scene, camera);
}

The problem is, I cannot see anything. If I change the material and use the commented one, a square appears as I would expect. Note that

  • The texture is 256x256, so its sides are power of two
  • The function is actually called when the body is loaded; indeed it works with a different material.
  • It does not work even if I serve the file from a webserver, so it is not an issue of cross-domain policy not allowing to load the image.

What I am I doing wrong?

Answer

Andrea picture Andrea · Oct 28, 2011

By the time the image is loaded, the renderer has already drawn the scene, hence it is too late. The solution is to change

texture = THREE.ImageUtils.loadTexture('crate.gif'),

into

texture = THREE.ImageUtils.loadTexture('crate.gif', {}, function() {
    renderer.render(scene);
}),