この記事は、Three.js Advent Calendar 2016 11日目の記事です。
three.jsでコンテンツを作る上でさけては通れないテクスチャーのロード処理。実は**PreloadJSを併用することで劇的に効率良くテクスチャーが扱えるようになることをご存知でしょうか?**今回はそんなマル秘テクニックを解説します。
TextureLoaderは一個のロードしかできない
three.jsに元々TextureLoader
というローダーが備わっています。次のコードはhoge.jpg
を読み込むためのコードです。
// テクスチャーのロード
var loader = new THREE.TextureLoader();
var texture = loader.load('hoge.jpg');
// マテリアルに貼り付け
var material = new THREE.MeshBasicMaterial( {
map: texture
});
TextureLoader
のload()
メソッドを使用して一つの画像を読み込んでいます。しかしこのままでは複数の画像を読み込みたい場合、。一個一個の画像に対してload()
メソッドを呼ぶ必要があります。ほとんどのプロジェクトの場合、テクスチャーは複数読み込む必要があるためTextureLoader
では非常に面倒です。しかしPreloadJSを併用することでこの問題が解決します。
PreloadJSとは
PreloadJSとはCreateJSが提供している**画像や音楽ファイルを読み込むためのモジュールです。**PreloadJSを使用することで複数のアセットの読み込みが可能になり、ローディング表示などの実装にも役立ちます。PreloadJSはCreateJSを使用せずとも単体で使用することができます。
three.jsとPrelaodJSを併用した簡単なデモを作成しました。GitHubにソースコードも置いていますので参考ください。
![Untitled.gif](https://qiita-image-store.s3.amazonaws.com/0/42248/8bc8f7ae-f779-a17e-8a68-43911762073b.gif)ここからPreloadJSを使用したテクスチャーロードの実装方法を解説しますがドキュメントを併せて見ておくと分かりやすいです。
PreloadJSでのテクスチャーロード実装
PreloadJSを使ったテクスチャーロード方法を解説します。まずはPreloadJSをHTMLで読み込みます。
<!-- PreloadJSの読み込み -->
<script src="https://code.createjs.com/preloadjs-0.6.2.min.js"></script>
PreloadJSを使用する準備が出来たのでJavaScriptを書いていきます。次のコードは画像を読み込んでthree.jsで使えるテクスチャーに変換するまでのコードです。
// 読み込むテクスチャーリスト
var manifest = [
{ id: 'hoge', src: './texture/hoge.png'},
{ id: 'huga', src: './texture/huga.png'}
];
// ロードキューを作成
var loadQueue = new createjs.LoadQueue();
// ロード完了を監視
loadQueue.on('complete', function() {
// loadQueueからロードした画像データを取得
var image = loadQueue.getResult('hoge');
// three.jsで使えるテクスチャーに変換
var texture = new THREE.Texture(image);
// 【重要】更新を許可
texture.needsUpdate = true;
});
// テクスチャーのロードを開始
loadQueue.loadManifest(manifest);
コードを順に解説していきます。
1. マニフェストデータを用意
読み込みたい画像の一覧データを配列で用意します。
// 読み込むテクスチャーリスト
var manifest = [
{ id: 'hoge', src: './texture/hoge.png'},
{ id: 'huga', src: './texture/huga.png'}
];
id
に設定した文字列は読み込み結果から画像を取得する際に使用します。分かりやすいid
を設定しましょう。src
には読み込みたい画像のパスを設定します。PreloadJSではこのような読み込みリストデータをManifestと呼びます。
2. LoadQueueを生成
LoadQueue
はローダーと思ってもらって差し支えありません。LoadQueue
を生成し、これを利用して画像のロードを行っていきます。
// ロードキューを作成
var loadQueue = new createjs.LoadQueue();
3. ロード完了イベントのリスナーを登録
ロード完了後の処理を追加します。全てのアセットのロードが完了するとcomplete
イベントが発火されるのでon()
メソッドでイベントリスナーを登録して監視します。
// ロード完了を監視
loadQueue.on('complete', function() {
// loadQueueからロードした画像データを取得
var image = loadQueue.getResult('hoge');
// three.jsで使えるテクスチャーに変換
var texture = new THREE.Texture(image);
// 【重要】更新を許可
texture.needsUpdate = true;
});
ロード完了後は**getResult()
メソッドにマニフェストで設定したIDを引数として渡すことで読み込んだ画像データを取得できます。**
// loadQueueからロードした画像データを取得
var image = loadQueue.getResult('hoge');
この時点でのimage
の中身は<image />
のようなタグ情報になっているのでこのままではテクスチャテクスチャーとして使用できません。この画像データを**THREE.Texture
のインスタンス生成時に引数として渡すことで初めてthree.jsで扱えるテクスチャーオブジェクトに変換されます。**
// three.jsで使えるテクスチャーに変換
var texture = new THREE.Texture(image);
**needsUpdate
をtrue
に設定することを必ず忘れないようにしてください!!**この設定を忘れるとテキスチャーが反映されず黒いMeshが表示されてしまいます。
// 【重要】更新を許可
texture.needsUpdate = true;
4. ロード開始
最後にloadManifest()
メソッドを使ってマニフェストで指定した画像の読み込みを開始します。
// テクスチャーのロードを開始
loadQueue.loadManifest(manifest);
使い方
読み込んだテクスチャーはそのままマテリアルの生成時にプロパティーとして渡すことで使用できます。
var material = new THREE.MeshPhongMaterial({
map: texture
});
尚、上記ではTHREE.Textureで説明しましたがTHREE.CubeTextureでも同じように読み込んだ画像から生成できます。SkyBoxでも同じ様に使えるので便利です。
// キューブテクスチャー
var texture = new THREE.CubeTexture([
loadQueue.getResult('px'),
loadQueue.getResult('nx'),
loadQueue.getResult('py'),
loadQueue.getResult('ny'),
loadQueue.getResult('pz'),
loadQueue.getResult('nz')
]);
texture.needsUpdate = true;
まとめ
今回紹介した方法を用いれば、テクスチャが読み込み終わっていないのにモデルが表示されてしまうなどの問題も解決できます。さらに、PreloadJSはテクスチャーだけでなく音楽ファイルも読み込めるのでthree.jsのローダーは使用せずにアセットのロードは**PreloadJSで一元管理したほうがプロジェクト内の見通しが良くなると思います。**アセットの読み込み周りでお困りであれば一度試してみてはいかがでしょうか。