私はTHREE.jsから始めて、単一の光源で照らされた、テクスチャーのある長方形を描画しようとしています。私はこれが得るのと同じくらい簡単だと思います(簡潔にするためにHTMLは省略されています):
function loadScene() {
var world = document.getElementById('world'),
WIDTH = 1200,
HEIGHT = 500,
VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000,
renderer = new THREE.WebGLRenderer(),
camera = new THREE.Camera(VIEW_ANGLE, ASPECT, NEAR, FAR),
scene = new THREE.Scene(),
texture = THREE.ImageUtils.loadTexture('crate.gif'),
material = new THREE.MeshBasicMaterial({map: texture}),
// material = new THREE.MeshPhongMaterial({color: 0xCC0000});
geometry = new THREE.PlaneGeometry(100, 100),
mesh = new THREE.Mesh(geometry, material),
pointLight = new THREE.PointLight(0xFFFFFF);
camera.position.z = 200;
renderer.setSize(WIDTH, HEIGHT);
scene.addChild(mesh);
world.appendChild(renderer.domElement);
pointLight.position.x = 50;
pointLight.position.y = 50;
pointLight.position.z = 130;
scene.addLight(pointLight);
renderer.render(scene, camera);
}
問題は、何も見えないことです。素材を変更してコメント付きのものを使用すると、予想どおり正方形が表示されます。ご了承ください
私は何を間違っていますか?
画像がロードされるまでに、レンダラーはすでにシーンを描画しているため、手遅れです。解決策は変更することです
texture = THREE.ImageUtils.loadTexture('crate.gif'),
に
texture = THREE.ImageUtils.loadTexture('crate.gif', {}, function() {
renderer.render(scene);
}),
アンドレアのソリューションは絶対に正しいです、私は同じアイデアに基づいて別の実装を書くだけです。 THREE.ImageUtils.loadTexture() source を見ると、javascript Imageオブジェクトを使用していることがわかります。 $(window).loadイベントは、すべての画像が読み込まれた後に発生します!そのイベントでは、既にロードされたテクスチャでシーンをレンダリングできます...
CoffeeScript
$(document).ready ->
material = new THREE.MeshLambertMaterial(map: THREE.ImageUtils.loadTexture("crate.gif"))
sphere = new THREE.Mesh(new THREE.SphereGeometry(radius, segments, rings), material)
$(window).load ->
renderer.render scene, camera
JavaScript
$(document).ready(function() {
material = new THREE.MeshLambertMaterial({ map: THREE.ImageUtils.loadTexture("crate.gif") });
sphere = new THREE.Mesh(new THREE.SphereGeometry(radius, segments, rings), material);
$(window).load(function() {
renderer.render(scene, camera);
});
});
ありがとう...
Three.jsのバージョンr75では、次を使用する必要があります。
var loader = new THREE.TextureLoader();
loader.load('texture.png', function ( texture ) {
var geometry = new THREE.SphereGeometry(1000, 20, 20);
var material = new THREE.MeshBasicMaterial({map: texture, overdraw: 0.5});
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
});
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 = ...
[...]
/**
* Will be called when load completes.
* The argument will be the loaded texture.
*/
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();
}
// Function called when download progresses
var onProgress = function (xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
};
// Function called when download errors
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
を使用して、同じコンテナ内に2つのメッシュを持つ新しいコンテナを作成します。
var Globe = function (radius, segments) {
THREE.Object3D.call(this);
this.name = "Globe";
var that = this;
// instantiate a loader
var loader = new THREE.TextureLoader();
すべてのオブジェクトにテクスチャファイルのtextures
とThree.js texture オブジェクトの値を格納するurl
が含まれるval
というマップ。
// earth textures
var textures = {
'map': {
url: 'relief.jpg',
val: undefined
},
'bumpMap': {
url: 'elev_bump_4k.jpg',
val: undefined
},
'specularMap': {
url: 'wateretopo.png',
val: undefined
}
};
textures
というマップ内の各オブジェクトのPromiseの配列。新しいPromiseを配列texturePromises
にプッシュすると、すべてのPromiseがloader.load
を呼び出します。 entry.val
の値が有効なTHREE.Texture
オブジェクトである場合、promiseを解決します。
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
は、約束配列texturePromises
を引数として取ります。そうすることで、すべての約束が解決するのをブラウザが待機します。約束が解決したら、ジオメトリとマテリアルをロードできます。
// load the geometry and the textures
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);
});
雲球の場合、必要なテクスチャは1つだけです。
// clouds
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;
エラー処理なし
//Load background texture
new THREE.TextureLoader();
loader.load('https://images.pexels.com/photos/1205301/pexels-photo-1205301.jpeg' , function(texture)
{
scene.background = texture;
});
エラー処理あり
// Function called when download progresses
var onProgress = function (xhr) {
console.log((xhr.loaded / xhr.total * 100) + '% loaded');
};
// Function called when download errors
var onError = function (error) {
console.log('An error happened'+error);
};
//Function called when load completes.
var onLoad = function (texture) {
var objGeometry = new THREE.BoxGeometry(30, 30, 30);
var objMaterial = new THREE.MeshPhongMaterial({
map: texture,
shading: THREE.FlatShading
});
var boxMesh = new THREE.Mesh(objGeometry, objMaterial);
scene.add(boxMesh);
var render = function () {
requestAnimationFrame(render);
boxMesh.rotation.x += 0.010;
boxMesh.rotation.y += 0.010;
sphereMesh.rotation.y += 0.1;
renderer.render(scene, camera);
};
render();
}
//LOAD TEXTURE and on completion apply it on box
var loader = new THREE.TextureLoader();
loader.load('https://upload.wikimedia.org/wikipedia/commons/thumb/9/97/The_Earth_seen_from_Apollo_17.jpg/1920px-The_Earth_seen_from_Apollo_17.jpg',
onLoad,
onProgress,
onError);
結果: