Three.js scene background doesn't appear - three.js

I'm trying to add a background to a webgl scene(Three.js). The scene contains two animated spritesheets that I created using DAZ3D and Photoshop. I've tried just about everything but to no avail, the background is either white or black. I've tried many examples on the web then either my spritesheet animator won't work or the background won't appear. I read that I need to make two scenes with two camera's, but that doesn't seem to work as well.
I really don't understand why I would need to have two scenes anyway.
<script>
// standard global variables
var container,scene,camera,renderer,controls,stats;
var keyboard = new THREEx.KeyboardState();
var clock = new THREE.Clock();
// custom global variables
var attack,defense;
init();
animate();
// FUNCTIONS
function init(){
// SCENE
scene = new THREE.Scene();
// CAMERA
var SCREEN_WIDTH = window.innerWidth,SCREEN_HEIGHT = window.innerHeight;
var VIEW_ANGLE = 45,ASPECT = SCREEN_WIDTH / SCREEN_HEIGHT,NEAR = 0.1,FAR = 1000;
var light = new THREE.PointLight(0xEEEEEE);
var lightAmb = new THREE.AmbientLight(0x777777);
camera = new THREE.PerspectiveCamera(VIEW_ANGLE,ASPECT,NEAR,FAR);
scene.add(camera);
camera.position.set(-10,30,400);
camera.lookAt(scene.position);
// RENDERER
if (Detector.webgl)
renderer = new THREE.WebGLRenderer({antialias:true});
else
renderer = new THREE.CanvasRenderer();
renderer.setSize(SCREEN_WIDTH,SCREEN_HEIGHT);
container = document.getElementById('ThreeJS');
container.appendChild(renderer.domElement);
// EVENTS
THREEx.WindowResize(renderer,camera);
THREEx.FullScreen.bindKey({charCode :'m'.charCodeAt(0)});
// LIGHTS
light.position.set(20,0,20);
scene.add(light);
scene.add(lightAmb);
// BACKGROUND
var texture = THREE.ImageUtils.loadTexture('images/sky.jpg');
var backgroundMesh = new THREE.Mesh(new THREE.PlaneGeometry(2,2,0),new THREE.MeshBasicMaterial({map:texture}));
backgroundMesh.material.depthTest = false;
backgroundMesh.material.depthWrite = false;
var backgroundScene = new THREE.Scene();
var backgroundCamera = new THREE.Camera();
backgroundScene.add(backgroundCamera);
backgroundScene.add(backgroundMesh);
// FLOOR
var floorTexture = new THREE.ImageUtils.loadTexture('images/checkerboard.jpg');
floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping;
floorTexture.repeat.set(10,10);
var floorMaterial = new THREE.MeshBasicMaterial({map:floorTexture,side:THREE.DoubleSide,shininess:30});
var floorGeometry = new THREE.PlaneGeometry(1000,1000);
var floor = new THREE.Mesh(floorGeometry,floorMaterial);
floor.position.y = -0.5;
floor.rotation.x = Math.PI / 2;
scene.add(floor);
// MESHES WITH ANIMATED TEXTURES!
var attackerTexture = new THREE.ImageUtils.loadTexture('images/kitinalevel2.png');
attack = new TextureAnimator(attackerTexture,2,13,26,25); // texture,#horiz,#vert,#total,duration.
var attackerMaterial = new THREE.MeshBasicMaterial({map:attackerTexture,side:THREE.DoubleSide,transparent:true});
var attackerGeometry = new THREE.PlaneGeometry(50,50,1,1);
var attacker = new THREE.Mesh(attackerGeometry,attackerMaterial);
attacker.position.set(-5,20,350);
scene.add(attacker);
var defenderTexture = new THREE.ImageUtils.loadTexture('images/kitinalevel1.png');
defense = new TextureAnimator(defenderTexture,2,13,26,25); // texture,#horiz,#vert,#total,duration.
var defenderMaterial = new THREE.MeshBasicMaterial({map:defenderTexture,side:THREE.DoubleSide,transparent:true});
var defenderGeometry = new THREE.PlaneGeometry(50,50,1,1);
var defenderx = new THREE.Mesh(defenderGeometry,defenderMaterial);
defenderx.position.set(25,20,350);
scene.add(defenderx);
}
function animate(){
requestAnimationFrame(animate);
render();
update();
}
function update(){
var delta = clock.getDelta();
attack.update(1000 * delta);
defense.update(1000 * delta);
//controls.update();
//stats.update();
}
function render(){
renderer.autoClear = false;
renderer.clear();
renderer.render(scene,camera);
renderer.render(backgroundScene,backgroundCamera);
}
function TextureAnimator(texture,tilesHoriz,tilesVert,numTiles,tileDispDuration){
// note:texture passed by reference,will be updated by the update function.
this.tilesHorizontal = tilesHoriz;
this.tilesVertical = tilesVert;
// how many images does this spritesheet contain?
// usually equals tilesHoriz * tilesVert,but not necessarily,
// if there at blank tiles at the bottom of the spritesheet.
this.numberOfTiles = numTiles;
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set(1 / this.tilesHorizontal,1 / this.tilesVertical);
// how long should each image be displayed?
this.tileDisplayDuration = tileDispDuration;
// how long has the current image been displayed?
this.currentDisplayTime = 0;
// which image is currently being displayed?
this.currentTile = 0;
this.update = function(milliSec){
this.currentDisplayTime += milliSec;
while(this.currentDisplayTime>this.tileDisplayDuration){
this.currentDisplayTime-=this.tileDisplayDuration;
this.currentTile++;
if (this.currentTile == this.numberOfTiles)
this.currentTile = 0;
var currentColumn = this.currentTile%this.tilesHorizontal;
texture.offset.x = currentColumn/this.tilesHorizontal;
var currentRow = Math.floor(this.currentTile/this.tilesHorizontal);
texture.offset.y = currentRow/this.tilesVertical;
}
};
}
</script>
What am I doing wrong?
Thanks in advance.

Found a solution:
renderer = new THREE.WebGLRenderer({antialias:true,alpha: true });
This will keep the background transparant, then with a little css I made the background appear.

Related

Three.js LegacyGLTFLoader.js shadows missing

I have a GLTF version 1.0 model that I am importing into Three.js using LegacyGLTFLoader.js. When I do so, everything looks good, except that the model does not receive shadows. I am guessing that this is because the imported model's material is THREE.RawShaderMaterial, which does not support receiving shadows (I think). How can I fix this so that my imported model can receive shadows?
Here is sample code:
// Construct scene.
var scene = new THREE.Scene();
// Get window dimensions.
var width = window.innerWidth;
var height = window.innerHeight;
// Construct camera.
var camera = new THREE.PerspectiveCamera(75, width/height);
camera.position.set(20, 20, 20);
camera.lookAt(scene.position);
// Construct renderer.
var renderer = new THREE.WebGLRenderer();
renderer.setSize(width, height);
renderer.shadowMapEnabled = true;
document.body.appendChild(renderer.domElement);
// Construct cube.
var cubeGeometry = new THREE.BoxGeometry(10, 1, 10);
var cubeMaterial = new THREE.MeshPhongMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
cube.castShadow = true;
cube.translateY(15);
scene.add(cube);
// Construct floor.
var floorGeometry = new THREE.BoxGeometry(20, 1, 20);
var floorMaterial = new THREE.MeshPhongMaterial({color: 0x00ffff});
var floor = new THREE.Mesh(floorGeometry, floorMaterial);
floor.receiveShadow = true;
scene.add(floor);
// Construct light.
var light = new THREE.DirectionalLight(0xffffff);
light.position.set(0, 20, 0);
light.castShadow = true;
scene.add(light);
// Construct light helper.
var lightHelper = new THREE.DirectionalLightHelper(light);
scene.add(lightHelper);
// Construct orbit controls.
new THREE.OrbitControls(camera, renderer.domElement);
// Construct GLTF loader.
var loader = new THREE.LegacyGLTFLoader();
// Load GLTF model.
loader.load(
"https://dl.dropboxusercontent.com/s/5piiujui3sdiaj3/1.glb",
function(event) {
var model = event.scene.children[0];
var mesh = model.children[0];
mesh.receiveShadow = true;
scene.add(model);
},
null,
function(event) {
alert("Loading model failed.");
}
);
// Animates the scene.
var animate = function () {
requestAnimationFrame(animate);
renderer.render(scene, camera);
};
// Animate the scene.
animate();
Here are my resources:
https://dl.dropboxusercontent.com/s/y2r8bsrppv0oqp4/three.js
https://dl.dropboxusercontent.com/s/5wh92lnsxz2ge1e/LegacyGLTFLoader.js
https://dl.dropboxusercontent.com/s/1jygy1eavetnp0d/OrbitControls.js
https://dl.dropboxusercontent.com/s/5piiujui3sdiaj3/1.glb
Here is a JSFiddle:
https://jsfiddle.net/rmilbert/8tqc3yx4/26/
One way to fix the problem is to replace the instance of RawShaderMaterial with MeshStandardMaterial. To get the intended effect, you have to apply the existing texture to the new material like so:
var newMaterial = new THREE.MeshStandardMaterial( { roughness: 1, metalness: 0 } );
newMaterial.map = child.material.uniforms.u_tex.value;
You also have to compute normal data for the respective geometry so lighting can be computed correctly. If you need no shadows, the unlint MeshBasicMaterial is actually the better choice.
Updated fiddle: https://jsfiddle.net/e67hbj1q/2/

How to change geometry color with dat.GUI?

I have the following code to render a simple cube. It has dat.GUI controls to change rotation, and I want to add a color changer also. Eventually, I want to have a more complex geometry and want to be able to change the color of more than one element.
$(function(){
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, .1, 500);
var renderer = new THREE.WebGLRenderer();
renderer.setClearColor(0xdddddd);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMapEnabled = true;
renderer.shadowMapSoft = true;
var axis = new THREE.AxisHelper(10);
scene.add (axis);
var grid = new THREE.GridHelper(50, 5);
var color = new THREE.Color("rgb(255,0,0)");
grid.setColors(color, 0x000000);
scene.add(grid);
var cubeGeometry = new THREE.BoxGeometry(5, 5, 5);
var cubeMaterial = new THREE.MeshLambertMaterial({color:0x80ff});
var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
var planeGeometry = new THREE.PlaneGeometry(30,30,30);
var planeMaterial = new THREE.MeshLambertMaterial({color:0xffffff});
var plane = new THREE.Mesh(planeGeometry, planeMaterial);
plane.rotation.x = -.5*Math.PI;
plane.receiveShadow = true;
scene.add(plane);
cube.position.x += 0.001;
cube.position.y = 2.5;
cube.position.z = 2.5;
scene.add(cube);
var spotLight = new THREE.SpotLight(0xffffff);
spotLight.castShadow = true;
spotLight.position.set (15,30,50);
scene.add(spotLight);
camera.position.x = 40;
camera.position.y = 40;
camera.position.z = 40;
camera.lookAt(scene.position);
var guiControls = new function(){
this.rotationX = 0.001;
this.rotationY = 0.001;
this.rotationZ = 0.001;
}
var datGUI = new dat.GUI();
datGUI .add(guiControls, 'rotationX', -30*Math.PI/180, 30*Math.PI/180);
datGUI .add(guiControls, 'rotationY', -30*Math.PI/180, 30*Math.PI/180);
datGUI .add(guiControls, 'rotationZ', -30*Math.PI/180, 30*Math.PI/180);
render();
function render() {
cube.rotation.x = guiControls.rotationX;
cube.rotation.y = guiControls.rotationY;
cube.rotation.z = guiControls.rotationZ;
requestAnimationFrame(render);
renderer.render(scene,camera);
}
$("#webGL-container").append(renderer.domElement);
renderer.render(scene,camera);
});
I have been able to add a gui to change color, but I cannot figure out how to bind the gui to the cube color.
var gui = new dat.GUI();
var folder = gui.addFolder('folder');
var params = {};
params.color = [255, 0, 255];
folder.addColor(params, 'color');
You can use dat.GUI to change the color of your cube by using a pattern like this one:
var params = {
color: 0xff00ff
};
var gui = new dat.GUI();
var folder = gui.addFolder( 'MATERIAL' );
folder.addColor( params, 'color' )
.onChange( function() { cube.material.color.set( params.color ); } );
folder.open();
three.js r.92

Three.js: Add different images to each side of cylinder

I am trying to add different image to each face of a cylinder in three.js, basically I want the top, bottom and side to be different images.
This is code where I have added one image which wraps the complete cylinder.
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var geometry = new THREE.CylinderGeometry(0.9,1,0.5,32,1, false);
var material = new THREE.MeshPhongMaterial({color: 0xffffff, side:THREE.DoubleSide, map: THREE.ImageUtils.loadTexture('cake-texture-nice-golden-ginger-33420104.jpg')});
var cone = new THREE.Mesh(geometry, material);
scene.add(cone);
var width = window.innerWidth; var height = window.innerHeight; var screenW = window.innerWidth; var screenH = window.innerHeight; /*SCREEN*/ var spdx = 0, spdy = 0; mouseX = 0, mouseY = 0, mouseDown = false; /*MOUSE*/ document.body.addEventListener("mousedown", function(event) { mouseDown = true }, false); document.body.addEventListener("mouseup", function(event) { mouseDown = false }, false); function animate() { spdy = (screenH / 2 - mouseY) / 40; spdx = (screenW / 2 - mouseX) / 40; if (mouseDown){ cone.rotation.x = spdy; cone.rotation.y = spdx; } requestAnimationFrame( animate ); render(); } // create a point light var pointLight = new THREE.PointLight( 0xFFFF8F ); // set its position pointLight.position.x = 10; pointLight.position.y = 50; pointLight.position.z = 130; // add to the scene scene.add(pointLight); camera.position.z = 5; var render = function () { requestAnimationFrame(render); //cone.rotation.x += 0.01; //cone.rotation.y += 0.001; //cone.rotation.z -= 0.02; window.addEventListener('mousemove', function (e) { var mouseX = ( e.clientX - width / 2 ); var mouseY = ( e.clientY - height / 2 ); cone.rotation.x = mouseY * 0.005; cone.rotation.y = mouseX * 0.005; cone.rotation.y += mouseY; //console.log(mouseY); }, false); renderer.render(scene, camera); }; render();
This is the pen for the cylinder: http://codepen.io/dilipmerani/pen/XmWNdV
Update-25Sep
var materialTop = new THREE.MeshPhongMaterial({color: 0xffffff, side:THREE.DoubleSide, map: THREE.ImageUtils.loadTexture('chocolate_brown_painted_textured_wall_tileable.jpg')});
var materialSide = new THREE.MeshPhongMaterial({color: 0xffffff, side:THREE.DoubleSide, map: THREE.ImageUtils.loadTexture('cake-texture-nice-golden-ginger-33420104.jpg')});
var materialBottom = new THREE.MeshPhongMaterial({color: 0xffffff, side:THREE.DoubleSide, map: THREE.ImageUtils.loadTexture('cake-texture-nice-golden-ginger-33420104.jpg')});
var materialsArray = [];
materialsArray.push(materialTop); //materialindex = 0
materialsArray.push(materialSide); // materialindex = 1
materialsArray.push(materialBottom); // materialindex = 2
var material = new THREE.MeshFaceMaterial(materialsArray);
var geometry = new THREE.CylinderGeometry(0.9,1,0.5,3,1, false);
var aFaces = geometry.faces.length;
console.log(aFaces);
for(var i=0;i<aFaces;i++) {
geometry.faces[i].materialindex;
}
var cone = new THREE.Mesh(geometry, material);
scene.add(cone);
Thanks
Create MeshFaceMaterial:
var materialTop = new THREE.MeshPhongMaterial(...);
var materialSide = new THREE.MeshPhongMaterial(...);
var materialBottom = new THREE.MeshPhongMaterial(...);
var materialsArray = [];
materialsArray.push(materialTop); //materialindex = 0
materialsArray.push(materialSide); // materialindex = 1
materialsArray.push(materialBottom); // materialindex = 2
var material = new THREE.MeshFaceMaterial(materialsArray);
Update geometry:
var geometry = new THREE.CylinderGeometry(0.9,1,0.5,32,1, false);
faces you can get from geometry.faces
Loop faces and change materialindex: geometry.faces[faceIndex].materialindex
Print geometry.faces to console and check what it has.
var aFaces = geometry.faces.length;
for(var i=0;i<aFaces;i++) {
if(i < 64){
geometry.faces[i].materialIndex = 0;
}else if(i > 63 && i < 96){
geometry.faces[i].materialIndex = 1;
}else{
geometry.faces[i].materialIndex = 2;
}
}
Build your cone
var cone = new THREE.Mesh(geometry, material);
Example of your updated code
You should create faces in mesh's geometry with some materialindex. So you'll have 3 surfaces. And than use MeshFaceMaterial(array of material for each surface).

Three.js FirstPersonControl does nothing

I implemented the following short script:
var screenWidth = window.innerWidth;
var screenHeight = window.innerHeight;
var camera;
var controls;
var scene;
var renderer;
var container;
var controls;
var keyboard = new THREEx.KeyboardState();
var clock = new THREE.Clock();
var light;
var floor;
var movingGeometry;
function setup()
{
var viewAngle = 45;
var aspect = screenWidth / screenHeight;
var near = 0.1;
var far = 20000;
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera(viewAngle, aspect, near, far);
camera.position.set(0,150,400);
camera.lookAt(scene.position);
scene.add(camera);
controls = new THREE.FirstPersonControls(camera);
controls.movementSpeed = 70;
controls.lookSpeed = 0.05;
controls.noFly = true;
controls.lookVertical = false;
renderer = new THREE.WebGLRenderer();
renderer.setSize(screenWidth, screenHeight);
container = document.getElementById('canvas');
container.appendChild( renderer.domElement );
createLight();
createFloor();
createSkyBox();
createGeometry();
animate();
}
function createLight()
{
light = new THREE.PointLight(0xffffff);
light.position.set(0,250,0);
scene.add(light);
}
function createFloor()
{
var floorMaterial = new THREE.MeshLambertMaterial({color: 0x00FF00});
floor = new THREE.Mesh(new THREE.BoxGeometry(1000, 1000, 3, 1, 1, 1), floorMaterial);
floor.position.y = -0.5;
floor.rotation.x = Math.PI / 2;
scene.add(floor);
}
function createSkyBox()
{
var skyBoxGeometry = new THREE.BoxGeometry(10000, 10000, 10000);
var skyBoxMaterial = new THREE.MeshBasicMaterial({color: 0x0000FF, side: THREE.BackSide});
var skyBox = new THREE.Mesh(skyBoxGeometry, skyBoxMaterial);
scene.add(skyBox);
}
function createGeometry()
{
var material = new THREE.MeshNormalMaterial();
var geometry = new THREE.BoxGeometry(50, 50, 50);
movingGeometry = new THREE.Mesh(geometry, material);
movingGeometry.position.set(0, 28, 0);
scene.add(movingGeometry);
}
function animate()
{
requestAnimationFrame(animate);
render();
update();
}
function render()
{
renderer.render(scene, camera);
controls.update();
}
function update()
{
var delta = clock.getDelta(); // seconds.
var moveDistance = 200 * delta; // 200 pixels per second
var rotateAngle = Math.PI / 2 * delta; // pi/2 radians (90 degrees) per second
if (keyboard.pressed("W"))
{
movingGeometry.translateZ(-moveDistance);
}
if (keyboard.pressed("S"))
{
movingGeometry.translateZ(moveDistance);
}
if (keyboard.pressed("A"))
{
movingGeometry.rotateOnAxis(new THREE.Vector3(0,1,0), rotateAngle);
}
if (keyboard.pressed("D"))
{
movingGeometry.rotateOnAxis(new THREE.Vector3(0,1,0), -rotateAngle);
}
var relativeCameraOffset = new THREE.Vector3(0,50,200);
var cameraOffset = relativeCameraOffset.applyMatrix4(movingGeometry.matrixWorld);
camera.position.x = cameraOffset.x;
camera.position.y = cameraOffset.y;
camera.position.z = cameraOffset.z;
camera.lookAt(movingGeometry.position);
}
I wanted to implement a camera which is sticking to an object. If i use 'w', 'a', 's', 'd' i can move the object and the camera follows. But i also want to be able to rotate the camera (at its position) by leftclick + dragging and i also want to rotate the object by rightclick + dragging (the typical first person behaviour).
So i added the FirstPersonControls from Three.js to the camera. The result: nothing happens when i use the mouse or click or anything and i also have no idea what i need to do to rotate the object by rightclicking and dragging.
Can someone help?
At first sight it seems like you have a problem with overwriting the cameras lookAt
Since in update() you do :
camera.lookAt(movingGeometry.position);
List item
Your order of execution order is:
animate
(your) render
(threejs) render
(threejs) controls update
(your) update
and in your update you overwrite the cameras lookat from the first person controls.

How do I make a material show up on a sphere

// set the scene size
var WIDTH = 1650,
HEIGHT = 700;
// set some camera attributes
var VIEW_ANGLE = 100,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;
// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('#container');
// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera( VIEW_ANGLE,
ASPECT,
NEAR,
FAR );
//camera.lookAt(new THREE.Vector3( 0, 0, 0 ));
var scene = new THREE.Scene();
// the camera starts at 0,0,0 so pull it back
camera.position.x = 200;
camera.position.y = 200;
camera.position.z = 300;
// start the renderer
renderer.setSize(WIDTH, HEIGHT);
// attach the render-supplied DOM element
$container.append(renderer.domElement);
// create the sphere's material
var sphereMaterial = new THREE.MeshLambertMaterial(
{
color: 0xCC0000
});
// set up the sphere vars
var radius = 60, segments = 20, rings = 20;
// create a new mesh with sphere geometry -
// we will cover the sphereMaterial next!
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(radius, segments, rings),
img);
// add the sphere to the scene
scene.add(sphere);
// and the camera
scene.add(camera);
// create a point light
var pointLight = new THREE.PointLight( 0xFFFFFF );
// set its position
pointLight.position.x = 50;
pointLight.position.y = 100;
pointLight.position.z = 180;
// add to the scene
scene.add(pointLight);
// add a base plane
var planeGeo = new THREE.PlaneGeometry(500, 500,8, 8);
var planeMat = new THREE.MeshLambertMaterial({color: 0x666699});
var plane = new THREE.Mesh(planeGeo, planeMat);
plane.position.x = 160;
plane.position.y = 0;
plane.position.z = 20;
//rotate it to correct position
plane.rotation.x = -Math.PI/2;
scene.add(plane);
// add 3D img
var img = new THREE.MeshBasicMaterial({
map:THREE.ImageUtils.loadTexture('cube.png')
});
img.map.needsUpdate = true;
// draw!
renderer.render(scene, camera);
I've put the var img as a material to the sphere but everytime I render it aoutomaticly changes color...
How do I do so it just will have the image as I want... not all the colors?
I whould possibly put the img on a plane.
You need to use the callback of the loadTexture function. If you refer to the source of THREE.ImageUtils you will see that the loadTexture function is defined as
loadTexture: function ( url, mapping, onLoad, onError ) {
var image = new Image();
var texture = new THREE.Texture( image, mapping );
var loader = new THREE.ImageLoader();
loader.addEventListener( 'load', function ( event ) {
texture.image = event.content;
texture.needsUpdate = true;
if ( onLoad ) onLoad( texture );
} );
loader.addEventListener( 'error', function ( event ) {
if ( onError ) onError( event.message );
} );
loader.crossOrigin = this.crossOrigin;
loader.load( url, image );
return texture;
},
Here, only the url parameter is required. The texture mapping can be passed in as null. The last two parameters are the callbacks. You can pass in a function for each one which will be called at the respective load and error events. The problem you are experiencing is most likely caused by the fact that three.js is attempting to apply your material before your texture is properly loaded. In order to remedy this, you should only do this inside a function passed as the onLoad callback (which will only be called after the image has been loaded up). Also, you should always create your material before you apply it to an object.
So you should change your code from:
// set up the sphere vars
var radius = 60, segments = 20, rings = 20;
// create a new mesh with sphere geometry -
// we will cover the sphereMaterial next!
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(radius, segments, rings),
img);
// add the sphere to the scene
scene.add(sphere);
to something like:
var sphereGeo, sphereTex, sphereMat, sphereMesh;
var radius = 60, segments = 20, rings = 20;
sphereGeo = new THREE.SphereGeometry(radius, segments, rings);
sphereTex = THREE.ImageUtils.loadTexture('cube.png', null, function () {
sphereMat = new THREE.MeshBasicMaterial({map: sphereTex});
sphereMesh = new THREE.Mesh(sphereGeo, sphereMat);
scene.add(sphereMesh);
});

Resources