在Three.js的r82版本中,
TextureLoader是用于加载纹理的对象。
加载一个纹理的方法如下(
源代码,
演示):
提取代码(
test.js):
var scene = new THREE.Scene();
var ratio = window.innerWidth / window.innerHeight;
var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight,
0.1, 50);
var renderer = ...
[...]
var onLoad = function (texture) {
var objGeometry = new THREE.BoxGeometry(20, 20, 20);
var objMaterial = new THREE.MeshPhongMaterial({
map: texture,
shading: THREE.FlatShading
});
var mesh = new THREE.Mesh(objGeometry, objMaterial);
scene.add(mesh);
var render = function () {
requestAnimationFrame(render);
mesh.rotation.x += 0.010;
mesh.rotation.y += 0.010;
renderer.render(scene, camera);
};
render();
}
var onProgress = function (xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
};
var onError = function (xhr) {
console.log('An error happened');
};
var loader = new THREE.TextureLoader();
loader.load('texture.jpg', onLoad, onProgress, onError);
多重纹理的加载 (源代码, 演示)
在这个例子中,纹理是在网格构造函数内加载的,使用Promises加载多重纹理。
提取(Globe.js):
使用Object3D
创建一个新容器,以便在同一容器中有两个网格:
var Globe = function (radius, segments) {
THREE.Object3D.call(this);
this.name = "Globe";
var that = this;
var loader = new THREE.TextureLoader();
一个名为textures
的地图,其中每个对象都包含纹理文件的url
和用于存储Three.js texture对象值的val
。
var textures = {
'map': {
url: 'relief.jpg',
val: undefined
},
'bumpMap': {
url: 'elev_bump_4k.jpg',
val: undefined
},
'specularMap': {
url: 'wateretopo.png',
val: undefined
}
};
对于地图中名为textures
的每个对象,在承诺数组中推入一个新承诺texturePromises
,每个承诺都将调用loader.load
。如果entry.val
的值是有效的THREE.Texture
对象,则解决该承诺。
var texturePromises = [], path = './';
for (var key in textures) {
texturePromises.push(new Promise((resolve, reject) => {
var entry = textures[key]
var url = path + entry.url
loader.load(url,
texture => {
entry.val = texture;
if (entry.val instanceof THREE.Texture) resolve(entry);
},
xhr => {
console.log(url + ' ' + (xhr.loaded / xhr.total * 100) +
'% loaded');
},
xhr => {
reject(new Error(xhr +
'An error occurred loading while loading: ' +
entry.url));
}
);
}));
}
Promise.all
接收一个 Promise 数组 texturePromises
作为参数。这样做会使浏览器等待所有 Promise 完成,当它们完成时,我们可以加载几何体和材质。
Promise.all(texturePromises).then(loadedTextures => {
var geometry = new THREE.SphereGeometry(radius, segments, segments);
var material = new THREE.MeshPhongMaterial({
map: textures.map.val,
bumpMap: textures.bumpMap.val,
bumpScale: 0.005,
specularMap: textures.specularMap.val,
specular: new THREE.Color('grey')
});
var earth = that.earth = new THREE.Mesh(geometry, material);
that.add(earth);
});
云领域只需要一张纹理:
loader.load('n_amer_clouds.png', map => {
var geometry = new THREE.SphereGeometry(radius + .05, segments, segments);
var material = new THREE.MeshPhongMaterial({
map: map,
transparent: true
});
var clouds = that.clouds = new THREE.Mesh(geometry, material);
that.add(clouds);
});
}
Globe.prototype = Object.create(THREE.Object3D.prototype);
Globe.prototype.constructor = Globe;
THREE.ImageUtils.loadTexture
,改用THREE.TextureLoader.load
。对于我来说,ImageUtils
完全不起作用,但是我第一次尝试TextureLoader
就完美地解决了问题。文档链接:https://threejs.org/docs/index.html#api/loaders/TextureLoader - ArtOfWarfare