【three.js】GLTF loaderで読み込んだモデルを透明にしたい


はじめに

three.jsでgltfモデルを読み込んで、そのモデルを透明にしたかったのです。
モデルを透明にするにはmaterialのプロパティを変更しなければならないのですが、細かいところで躓いてしまったのでメモです。

失敗例

const gltfLoader = new THREE.GLTFLoader();
gltfLoader.load('XXX.glb', (gltf) => {
    const model = gltf.scene; //モデルを取得
    model.material.transparent = true; //マテリアルの設定変更
    model.material.opacity = 0.5; //マテリアルの設定変更
    scene.add(gltf.scene);
})

最初こうやっていたのですが、これだとmodel.materialundefinedになります。
それもそのはず、gltf.sceneSceneオブジェクトのインスタンスです。
materialにアクセスできるMeshではありません!
シーンに追加するときにscene.add(gltf.scene)ってやるので、てっきりMeshかと勘違いしてました。(そもそもgltf.sceneって書いてあるじゃん。。)

gltf.sceneの構造ですが、ロードしたgltf.scene自体は一個の大きな親で、その配下にたくさんの要素がある構造のようです。
なので解決策としては、gltf.sceneを構成している要素に含まれているMeshにアクセスすればよい、ということになります。
sceneの子要素にアクセスするためには、traverseを使用します。

成功例

const gltfLoader = new THREE.GLTFLoader();
gltfLoader.load('XXX.glb', (gltf) => {
    const model = gltf.scene; //モデルを取得
    model.traverse((object) => { //モデルの構成要素をforEach的に走査
        if(object.isMesh) { //その構成要素がメッシュだったら
	    object.material.trasparent = true;
	    object.material.opacity = 0.5;
	}
    });
    scene.add(gltf.scene);
})

これでMeshにアクセスして、materialを透明にできました!


※3Dモデルの出典( https://poly.google.com/view/1L9oJAw6nY2

めでたし。

おまけ:Webで3Dモデルを使用する際の注意点

おまけですが、Webで3Dモデルを使用する際はやっぱり軽くないとダメですね。
特にモバイルでも見せたい場合。あまりにも重いと読み込み時点でブラウザがクラッシュします。
わかりやすい目安をWebARのプラットフォームである8thwallさんが示してくれていて、

  • ファイルサイズが小さくなる、「.glb」形式ファイルが望ましい
  • 一つのモデルのファイルサイズは10MBまで

が良いようです。
※glbはgltfのバイナリファイルで、GLTF Loaderで読み込み可能です。
gltfを持っていて、glbに変換したい方は「 https://sbtron.github.io/makeglb/
こちらが便利!

また、objしか持っていない方も、gltfにはオンラインで変換できるサイトが結構あります。