A-Frame で glb を表示すると暗くなる件

Oculus Go が出てから WebVR ( A-Frame ) でいろいろこっそり作ってみている。
ノウハウもそこそこ溜まってきて、アウトプットしようかなと思いつつもサボりっぱなし(苦笑

いろんな角度から撮った写真から 3D モデルを生成する photogrammetry ツールの 3DF Zephyr が楽しくて、3D モデルにしたらおもしろそうと思うようなものを写真取りまくって試している。
たとえばお寿司。

 


Photogrammetry(3DF Zephyr)でお寿司回してみた

 

こうした 3D モデルはなにがしかのフォーマットで保存するわけだが、とりあえず最初に使った obj+mtl 形式をずっと使ってきた。
後で調べると、まあずいぶんわんさかとある( Template:3Dファイル形式 - Wikipedia )。どれがいいのか比べて検討してみたが、obj+mtl をサポートしていないツールって基本無くて、交換用フォーマットとしてはなんだかんだ一番ポータビリティ高いのかも、と思ってたりする。

glTF は次の標準を狙っているということと OpenGL に最適化しているということで気になったけど、Blender がエクスポートできるのにインポートできない(要別途プラグイン)など、意外とサポートしてないツールがちょいちょいあるのが難点。
そして、A-Frame はちゃんと glTF をサポートしているのだけど、これで gltf/glb を表示するとなぜか暗くなるという現象があって、使うのをやめていた。


同じ 3DF Zepher からエクスポートした obj と glb(glTF のバイナリ形式) を A-Frame で表示すると見た目がこれくらい変わる。
モデルはサイボウズのエントランスにいるキリンのぬいぐるみ(「こきりんとーん」という名前)を 3DF Zephyr で 3D モデル化したもの。
(真ん中に浮いてるキューブは、後の対策で色がどう変わってしまうか見るために入れている)

 
f:id:n_shuyo:20181128161746j:plain

 

ライティングをいろいろ工夫したがなんともならない。directional light をあてても暗いままなので、どうも「暗い」と言うより「黒い」らしい。
3DF Zephyr で出力したものが悪いのかと、obj を Blender や MS 3D Builder で読んで glb にしても症状変わらず。
glb を A-Frame で表示したいなんてすごくよくある話だと思うんだが、ネットで探してもそれらしい情報はなぜか出てこない。手詰まり。

というわけで glb の使用はあきらめていたのだが、obj と glb の Oculus Go でのロード時間を比べると、大きいときは glb が 300ms くらいのときに obj+mtl が 3000ms と10倍から違う。*1

このモデルのロード(正確にはおそらくグラフィックメモリへの転送)中は完全に止まってしまう。初回表示時の 1回だけとはいえ 3秒待ちは体験を大きく損ねる。

そうなると「 glb 暗くなる問題」をなんとか解消して glb を使いたいところ。本腰を入れて探して、 Three.js の issue でようやくそれらしい情報に突き当たった。

GLTFLoader display model is darker · Issue #12554 · mrdoob/three.js · GitHub

長いんでテキトーに要約すると、まさに gltf だと暗くなるよ問題で、同様に glb を作るツールによらず起きるので データの問題ではないと報告。にもかかわらず、これ Three.js のせいじゃないよと close されたあと、問題を再認識して、"So... what's going on here?" で終了。えー困るー。

ただここには renderer.gammaOutput = true; したらいいよ、という情報も書かれていた。Three.js の renderer は、A-Frame では <a-scene> からアクセスできる。具体的には、

document.querySelector("a-scene").renderer.gammaOutput=true;

を </body> の後ろとか、ページの表示完了イベントとかで実行すればいい。

上のキリンで実行すると次のようになり、 glb モデルが期待する明るさになった!

 

f:id:n_shuyo:20181128161752j:plain

ただし見てわかる通り、確かに glb キリンは元の obj キリンと同じ明るさになったが、glb 以外のオブジェクトが明るすぎる……。

まだこの新しい問題は解決できていないが、「どうやっても暗い(黒い)」と違って対処のしようはあるので、一歩前進?

 

*1:同時表示可能オブジェクト数でも glb のほうが若干 obj より有利。といっても本当に「若干」で、巨大なテクスチャのモデルについて、obj だと12個表示したらブラウザが落ちるか VR モードが強制解除されるところ、glb だと13個表示できる「ことがある」くらいの差……。