Javascript three.js:重用纹理?
在我的程序中,我有几个地方实例化几何体,每个地方都有自己的偏好,以确定如何对其几何体进行网格划分(双面还是非双面?Lambert还是基本材质?)。但是,它们都使用相同的纹理。我只想加载这个普通纹理一次。这给了我一个设计问题: 当使用Javascript three.js:重用纹理?,javascript,three.js,Javascript,Three.js,在我的程序中,我有几个地方实例化几何体,每个地方都有自己的偏好,以确定如何对其几何体进行网格划分(双面还是非双面?Lambert还是基本材质?)。但是,它们都使用相同的纹理。我只想加载这个普通纹理一次。这给了我一个设计问题: 当使用TextureLoader.load()加载纹理时,我只能使用一次纹理,也就是说,在传递给load函数的回调函数中。这意味着,在加载纹理之前,我必须收集所有几何体实例及其每个首选项,以便在启动加载时(通过闭包)使其可用于回调函数 我在想是否有一个标准的方法来解决这个问
TextureLoader.load()
加载纹理时,我只能使用一次纹理,也就是说,在传递给load
函数的回调函数中。这意味着,在加载纹理之前,我必须收集所有几何体实例及其每个首选项,以便在启动加载时(通过闭包)使其可用于回调函数
我在想是否有一个标准的方法来解决这个问题?我想其他3.js用户可能也遇到过类似的情况。我知道如何使用承诺来解决这个问题:load函数将返回表示纹理的承诺。然后,可以将该纹理传递到需要网格几何体的每个站点。这个解决方案很方便,因为我不必收集大量的几何数据,只需在稍后的一个步骤中传递
但是,对于这个问题,有没有一个类似的、或者几乎同样方便的解决方案,仍然停留在回调语义的领域呢?我最终选择了承诺路线:包装
TextureLoader.load()
调用Javascripts内置的承诺返回构造函数,名为Promise
:
var loadTexture_promise = ( texture_path, texture_loader ) => {
var texture_promise;
if ( loadTexture_promise.texturePromises_cache[texture_path] !== undefined ) {
return loadTexture_promise.texturePromises_cache[texture_path]
}
texture_promise = new Promise(
function( resolve, reject )
{
texture_loader.load(
texture_path,
function (texture) {
// Success callback of TextureLoader
// We're done, so tell the promise it is complete
resolve(texture);
},
function (XmlHttpRequest_instance) {
// Progress callback of TextureLoader
},
function (unknown_parameter) {
// Failure callback of TextureLoader
// Reject the promise with the failure
reject(new Error('Could not load texture ' + texture_path));
}
);
}
);
// add texture_promise to cache:
loadTexture_promise.texturePromises_cache[texture_path] = texture_promise;
return texture_promise;
};
// establish cache object on the loadTexture_promise function:
loadTexture_promise.texturePromises_cache = [];
然后,我有一个lambertmasher
函数,几何体供应商可以调用该函数:
function lambertMesher ( aGeometry, aTexture_promise, doubleSided, debug ) {
var aMesh_promise = aTexture_promise.then(
( resolved_texture ) =>
{
var material, mesh;
if ( debug ) {
console.log("resolved_texture: ", resolved_texture);
console.log("aGeometry: ", aGeometry);
}
resolved_texture.minFilter = THREE.NearestFilter;
if (doubleSided) {
material = new THREE.MeshLambertMaterial( { map: resolved_texture, side: THREE.DoubleSide } );
} else {
material = new THREE.MeshLambertMaterial( { map: resolved_texture, emissive: 0xffffff } );
}
mesh = new THREE.Mesh(aGeometry, material);
if ( debug ) {
console.log("mesh: ", mesh);
}
return mesh
},
( reason_of_textureLoading_failure ) =>
{
console.log( "meshing failed. Also: " + reason_of_textureLoading_failure )
}
);
return aMesh_promise
}
最后,我这样称呼我的lambertmasher
:
var myPlateGeom = new THREE.PlateGeometry( myPlatePolygonSet, true );
var myPlateMesh_promise = utils_meshers.lambertMesher( myPlateGeom, myRobinieTexture_promise, true, false );
最后,我将网格添加到场景中,如下所示:
myPlateMesh_promise.then(
(myPlateMesh) => { myScene.add( myPlateMesh ) },
(reason) => console.log( "failed to add myPlateMesh. Also: " + reason )
);
因为您需要等待纹理加载,所以承诺是最适合这里的。承诺的好处在于,您可以继续调用
。然后()
,这样可以保持代码的整洁。听起来你不需要承诺方面的帮助,但我以前也回答过类似的问题: