Skip to content Skip to sidebar Skip to footer

Three.js: Texture Goes All White

EDIT: Following gaitat's suggestion for a fix, I got a new error: now the box doesn't show up at all. I've written a new question to demonstrate this error. I have a simple geometr

Solution 1:

So, the code turned out to contain three errors, as each pointed out by Falk Thiele and 2pha/gaitat in the follow up question that I posted:

  1. 'A Cross-origin resource sharing' (CORS) issue, promting the following error in Firebug:

    SecurityError: The operation is insecure.
    gl.texImage2D.apply( gl, arguments );
    

    Quoting from Falk Thiele this error is fixed by setting the CrossOrigin attribute to empty:

    var loader = newTHREE.TextureLoader();
    loader.crossOrigin = "";
    loader.load(
        "http://mrdoob.github.io/three.js/examples/textures/crate.gif",
        function( texture ) {
            //...
        },
        function () {},  // onProgress functionfunction ( error ) { console.log( error ) } // onError function
    );
    

    Oddly, one can also get a CORS-error (in Chrome) when loading the crate.gif texture locally. This happens if one includes the loader.crossOrigin = ""; line. Thus it seems this line should only be used if one is certain that the origin is indeed of cross site origin.

  2. The scene is only being rendered once, and this one rendering happens before the texture has been loaded. This is because the TextureLoader.load() call works asynchronously, thus letting the later code line renderer.render( scene, camera ); execute before the calling of load has finished.

  3. The script failed to work in Chrome, for two reasons: First the CORS-problem described above, and second, the script for some reason failing to load the THREE library (Uncaught ReferenceError: THREE is not defined). I don't know why THREE failed to load in Chrome, but in the error corrected code (seen below, and also here) the error no longer appears, so for now the cause remains unknown.

Finally, I have made a JS fiddle demonstrating the running code.

Here is the error corrected code snippet with errors 1, 2 and 3 no longer present:

"use strict";

// make DOM elements:var container = document.createElement( 'div' );
document.body.appendChild( container );
var info = document.createElement( 'div' );
container.appendChild( info );

// a 'Box2' geometry instance:  (see geometry implementation below)var myBox2geom = newTHREE.BoxGeometry( 100, 100, 100, 10, 10, 10 );  // args: x,y,z-dimensions and width of their segments// create scene:var scene = newTHREE.Scene();

// make a corresponding 'Box2' mesh:var loader = newTHREE.TextureLoader();
loader.crossOrigin = "";
loader.load("http://mrdoob.github.io/three.js/examples/textures/crate.gif",
	function ( texture ) {
		texture.minFilter = THREE.NearestFilter;
		var material = newTHREE.MeshLambertMaterial( { map: texture, side: THREE.DoubleSide } );
		var myBox2mesh = newTHREE.Mesh(myBox2geom, material);
		// add mesh to scene:
		scene.add( myBox2mesh );
	},
	function () {},  // onProgress functionfunction ( error ) { console.log( error ) }  // no error gets logged
);

// make light:var light = newTHREE.PointLight( 0xffffff );
light.position.set(100, 200, 300);
light.lookAt( newTHREE.Vector3( 0, 0, 0 ) );
scene.add( light );

// make camera:var camera = newTHREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
camera.position.x = 100;
camera.position.y = 200;
camera.position.z = 300;
camera.lookAt( newTHREE.Vector3( 0, 0, 0 ) );
scene.add( camera );

// make renderer:var renderer = newTHREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );

// aaaand render, continuously!functionanimate() {
	requestAnimationFrame( animate );
	renderer.render( scene, camera );
}
animate();



THREE.Box2Geometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {

	THREE.Geometry.call( this );

	this.parameters = {
		width: width,
		height: height,
		depth: depth,
		widthSegments: widthSegments,
		heightSegments: heightSegments,
		depthSegments: depthSegments
	};

	this.widthSegments = widthSegments || 1;
	this.heightSegments = heightSegments || 1;
	this.depthSegments = depthSegments || 1;

	var constructee = this;  // constructee = the instance currently being constructed by the Box2Geometry constructorvar width_half = width / 2;    // width  = the distance along x in the absolute 3D spacevar height_half = height / 2;  // height = the distance along y in the absolute 3D spacevar depth_half = depth / 2;    // depth  = the distance along z in the absolute 3D spacebuildPlane( 'z', 'y', -1, -1, depth, height, width_half, 0 ); // pxbuildPlane( 'z', 'y',  1, -1, depth, height, -width_half, 1 ); // nxbuildPlane( 'x', 'z',  1,  1, width, depth, height_half, 2 ); // pybuildPlane( 'x', 'z',  1, -1, width, depth, -height_half, 3 ); // nybuildPlane( 'x', 'y',  1, -1, width, height, depth_half, 4 ); // pzbuildPlane( 'x', 'y', -1, -1, width, height, -depth_half, 5 ); // nzfunctionbuildPlane( u, v, uDir, vDir, uDist, vDist, wDist_half, materialIndex ) {

		var w, iu, iv,
			segU = constructee.widthSegments,  // number of segments along u   // width  = x
			segV = constructee.heightSegments, // number of segments along v   // height = y
			uDist_half = uDist / 2,  // the extent of the plane along u, divided by two
			vDist_half = vDist / 2,  // the extent of the plane along v, divided by two
			offset = constructee.vertices.length;

		if ( ( u === 'x' && v === 'y' ) || ( u === 'y' && v === 'x' ) ) {

			w = 'z';

		} elseif ( ( u === 'x' && v === 'z' ) || ( u === 'z' && v === 'x' ) ) {

			w = 'y';
			segV = constructee.depthSegments;

		} elseif ( ( u === 'z' && v === 'y' ) || ( u === 'y' && v === 'z' ) ) {

			w = 'x';
			segU = constructee.depthSegments;

		}

		var segUi = segU + 1,  // i = inc = incremented (by one)
			segVi = segV + 1,  // i = inc = incremented (by one)
			segmentDist_u = uDist / segU,
			segmentDist_v = vDist / segV,
			normal = newTHREE.Vector3();

		normal[ w ] = wDist_half > 0 ? 1 : -1;

		for ( iv = 0; iv < segVi; iv++ ) {

			for ( iu = 0; iu < segUi; iu++ ) {

				var vertex = newTHREE.Vector3();
				vertex[ u ] = ( iu * segmentDist_u - uDist_half ) * uDir;
				vertex[ v ] = ( iv * segmentDist_v - vDist_half ) * vDir;
				vertex[ w ] = wDist_half;

				constructee.vertices.push( vertex );

			}

		}

		for ( iv = 0; iv < segV; iv++ ) {

			for ( iu = 0; iu < segU; iu++ ) {

				var a = iu         + segUi *   iv;
				var b = iu         + segUi * ( iv + 1 );
				var c = ( iu + 1 ) + segUi * ( iv + 1 );
				var d = ( iu + 1 ) + segUi *   iv;

				var uva = newTHREE.Vector2(   iu       / segU, 1 -   iv       / segV );
				var uvb = newTHREE.Vector2(   iu       / segU, 1 - ( iv + 1 ) / segV );
				var uvc = newTHREE.Vector2( ( iu + 1 ) / segU, 1 - ( iv + 1 ) / segV );
				var uvd = newTHREE.Vector2( ( iu + 1 ) / segU, 1 -   iv       / segV );

				var face1 = newTHREE.Face3( a + offset, b + offset, d + offset );
				face1.normal.copy( normal );
				face1.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
				face1.materialIndex = materialIndex;

				constructee.faces.push( face1 );
				constructee.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );

				var face2 = newTHREE.Face3( b + offset, c + offset, d + offset );
				face2.normal.copy( normal );
				face2.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
				face2.materialIndex = materialIndex;

				constructee.faces.push( face2 );
				constructee.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );

			}

		}

	}

	this.mergeVertices();
};
THREE.Box2Geometry.prototype = Object.create( THREE.Geometry.prototype );
<!doctype html><html><head><metacharset="utf-8"><metaname="viewport"content="width=device-width, initial-scale=1, user-scalable=no"></head><body><scriptsrc="https://raw.githubusercontent.com/mrdoob/three.js/master/build/three.js"></script><scriptsrc="main3.js"></script></body></html>

EDIT: A fourth type of error that can cause a texture to go white (if it is emissive on its own) or black (if it isn't) is if there are no lights, or the lights aren't being added to the scene, or the lights are pointing in the wrong direction (tip: use light.lookAt()) or the lights are too far away from the mesh.

EDIT 2: A fifth reason is if the face normals aren't pointing outwards from the geometry. See the question three.js: custom geometry wont be textured for details.

Solution 2:

If you want to be sure that your texture is loaded you need to use the THREE.Textureloader().onLoad() function.

Here is how your example would work:

// make DOM elements:var container = document.createElement( 'div' );
document.body.appendChild( container );

var scene = newTHREE.Scene();

// a 'Box2' geometry instance:  (see geometry implementation below)var myBox2geom = newTHREE.BoxGeometry( 100, 100, 100, 10, 10, 10 );  // args: x,y,z-dimensions and width of their segments// instantiate a loadervar loader = newTHREE.TextureLoader();

// load a resource
loader.load(
    'crate.gif',    // resource URLfunction ( texture ) {
        texture.minFilter = THREE.NearestFilter;

        var material = newTHREE.MeshLambertMaterial( { map: texture } );

        var myBox2mesh = newTHREE.Mesh(myBox2geom, material);

        // add mesh to scene:
        scene.add( myBox2mesh );
    },
);

// make light:var light = newTHREE.PointLight( 0xffffff );
light.position.set(100, 200, 300);
light.lookAt( newTHREE.Vector3( 0, 0, 0 ) );
scene.add( light );

// make camera:var camera = newTHREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.set( 100, 200, 300 );
camera.lookAt( newTHREE.Vector3( 0, 0, 0 ) );

// make renderer:var renderer = newTHREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );

animate();

functionanimate() {

    requestAnimationFrame( animate );
    renderer.render( scene, camera );

}

Post a Comment for "Three.js: Texture Goes All White"