三.js:纹理全白 [英] three.js: texture goes all white

查看:41
本文介绍了三.js:纹理全白的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按照 gaitat 的修复建议,我收到一个新错误:现在盒子没有出现在所有.我写了一个新问题来证明这个错误.

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.

我有一个简单的盒子几何图形,我想用纹理装饰它.然而,我得到的只是一个 100% 的白盒子.我编写了一个简单的测试站点来演示这个问题.这是该网站的内容:

I have a simple geometry for a box, that I'm trying to decorate with a texture. However, all I get is a 100% white box. I've written a simple test site to demonstrate this issue. This is the content of that site:

"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 = new THREE.BoxGeometry( 100, 100, 100, 10, 10, 10 );  // args: x,y,z-dimensions and width of their segments

// make a corresponding 'Box2' mesh:
var texture = new THREE.TextureLoader().load( "crate.gif" );
			console.log("texture: ", texture);
var material = new THREE.MeshLambertMaterial( { map: texture, side: THREE.DoubleSide, emissive:0xffffff } );
texture.minFilter = THREE.NearestFilter;
var myBox2mesh = new THREE.Mesh(myBox2geom, material);

// add mesh to scene:
var scene = new THREE.Scene();
scene.add( myBox2mesh );

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

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

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

// aaaand render!
renderer.render( scene, camera );



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 constructor

	var width_half = width / 2;    // width  = the distance along x in the absolute 3D space
	var height_half = height / 2;  // height = the distance along y in the absolute 3D space
	var depth_half = depth / 2;    // depth  = the distance along z in the absolute 3D space

	buildPlane( 'z', 'y', -1, -1, depth, height, width_half, 0 ); // px
	buildPlane( 'z', 'y',  1, -1, depth, height, -width_half, 1 ); // nx
	buildPlane( 'x', 'z',  1,  1, width, depth, height_half, 2 ); // py
	buildPlane( 'x', 'z',  1, -1, width, depth, -height_half, 3 ); // ny
	buildPlane( 'x', 'y',  1, -1, width, height, depth_half, 4 ); // pz
	buildPlane( 'x', 'y', -1, -1, width, height, -depth_half, 5 ); // nz

	function buildPlane( 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';

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

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

		} else if ( ( 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 = new THREE.Vector3();

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

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

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

				var vertex = new THREE.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 = new THREE.Vector2(   iu       / segU, 1 -   iv       / segV );
				var uvb = new THREE.Vector2(   iu       / segU, 1 - ( iv + 1 ) / segV );
				var uvc = new THREE.Vector2( ( iu + 1 ) / segU, 1 - ( iv + 1 ) / segV );
				var uvd = new THREE.Vector2( ( iu + 1 ) / segU, 1 -   iv       / segV );

				var face1 = new THREE.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 = new THREE.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>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
  </head>
  <body>
    <script src="https://raw.githubusercontent.com/mrdoob/three.js/master/build/three.js"></script>
    <script src="main.js"></script>
  </body>
</html>

推荐答案

因此,代码结果包含三个错误,正如 Falk Thiele2pha/gaitat我提出的后续问题发布:

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. 跨源资源共享"(CORS) 问题,在 Firebug 中提示以下错误:

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

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

引用自 Falk Thiele 这个错误是通过将 CrossOrigin 属性设置为空来修复的:

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

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

奇怪的是,在本地加载 crate.gif 纹理时,也可能出现 CORS 错误(在 Chrome 中).如果包含 loader.crossOrigin = ""; 行,就会发生这种情况.因此,似乎只有在确定来源确实是跨站点来源的情况下,才应该使用这一行.

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.

scene 只被渲染一次,而这一次渲染发生在纹理加载之前.这是因为 TextureLoader.load() 调用是异步工作的,因此让后面的代码行 renderer.render(scene, camera ); 在调用 之前执行加载已完成.

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.

脚本无法在 Chrome 中运行,原因有二:首先是上述 CORS 问题,其次,脚本由于某种原因未能加载 THREE 库(Uncaught ReferenceError: THREE is not定义).我不知道为什么在 Chrome 中加载失败,但在错误更正的代码中(见下文,还有 此处) 错误不再出现,所以现在原因仍然未知.

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.

最后,我制作了一个 JS fiddle 演示运行代码.

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

这是错误更正后的代码片段,错误 1、2 和 3 不再存在:

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 = new THREE.BoxGeometry( 100, 100, 100, 10, 10, 10 );  // args: x,y,z-dimensions and width of their segments

// create scene:
var scene = new THREE.Scene();

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

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

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

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

// aaaand render, continuously!
function animate() {
	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 constructor

	var width_half = width / 2;    // width  = the distance along x in the absolute 3D space
	var height_half = height / 2;  // height = the distance along y in the absolute 3D space
	var depth_half = depth / 2;    // depth  = the distance along z in the absolute 3D space

	buildPlane( 'z', 'y', -1, -1, depth, height, width_half, 0 ); // px
	buildPlane( 'z', 'y',  1, -1, depth, height, -width_half, 1 ); // nx
	buildPlane( 'x', 'z',  1,  1, width, depth, height_half, 2 ); // py
	buildPlane( 'x', 'z',  1, -1, width, depth, -height_half, 3 ); // ny
	buildPlane( 'x', 'y',  1, -1, width, height, depth_half, 4 ); // pz
	buildPlane( 'x', 'y', -1, -1, width, height, -depth_half, 5 ); // nz

	function buildPlane( 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';

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

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

		} else if ( ( 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 = new THREE.Vector3();

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

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

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

				var vertex = new THREE.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 = new THREE.Vector2(   iu       / segU, 1 -   iv       / segV );
				var uvb = new THREE.Vector2(   iu       / segU, 1 - ( iv + 1 ) / segV );
				var uvc = new THREE.Vector2( ( iu + 1 ) / segU, 1 - ( iv + 1 ) / segV );
				var uvd = new THREE.Vector2( ( iu + 1 ) / segU, 1 -   iv       / segV );

				var face1 = new THREE.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 = new THREE.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>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
  </head>
  <body>
    <script src="https://raw.githubusercontent.com/mrdoob/three.js/master/build/three.js"></script>
    <script src="main3.js"></script>
  </body>
</html>

可能导致纹理变白(如果它本身是自发光的)或变黑(如果不是)的第四种类型的错误是没有灯,或者灯没有被添加到场景中,或者灯光指向错误的方向(提示:使用 light.lookAt())或者灯光离网格太远.

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.

编辑 2:第五个原因是面法线没有从几何体向外指向.有关详细信息,请参阅问题 three.js:自定义几何体不会被纹理化.

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.

这篇关于三.js:纹理全白的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆