three.js:纹理全黑 [英] three.js: texture goes all black

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

问题描述

我有一个简单的盒子几何形状,我正试图用纹理装饰。但是,我的盒子根本没有显示(或者可能是100%黑色)。这个当前的问题是从这个问题演变而来的。我已更新代码以反映 gaitat 在原始问题上给出的答案。我已经写了另一个简单的测试网站来演示这个新问题。这是该网站的内容:

I have a simple geometry for a box, that I'm trying to decorate with a texture. However, my box doesn't show at all (or perhaps it is 100% black). This current question is evolved from this question. I've updated the code to reflect the answer given by gaitat on the original question. I've written another simple test site to demonstrate this new 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

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

// make a corresponding 'Box2' mesh:
new THREE.TextureLoader().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!
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="main2.js"></script>
  </body>
</html>

推荐答案

因此,代码结果包含三个错误,每个错误都由 Falk Thiele 和 2pha / gaitat

So, the code turned out to contain three errors, as each pointed out by Falk Thiele and 2pha/gaitat:


  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
);

奇怪的是,加载<$ c $时,也会出现CORS错误(在Chrome中) c> crate.gif 本地纹理。如果包含 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); 在调用 load 之前执行。

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库(未捕获的ReferenceError:THREE未定义) 。我不知道为什么THREE无法在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小提示演示正在运行的代码

以下是错误更正的代码段,错误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>

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

A fourth type of error that can cause a texture to go white (if it is emissive on its own) or go 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.

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

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