three.jsで遊んでみる(29)

 プログラム,
 公開日:2014年6月9日 / 更新日:2014年8月27日

前回の続きです。

こちらの Change Log を参照して、
r58 から r67 にベースを上げるにあたって、
今回の変更で考慮すべき点、気になった点を書いてみます。

・Object3Dとかにuuidを導入。
 オブジェクトを識別するためだと思いますが、メモリ使用量が増えますね。
 個人的にはuuidは無くてもあまり困らない気がしますが。

・オイラー角がVector3から新設のEulerへ移行。
 位置・方向と回転は明確に区別した方が良いということなのでしょう。

・Face4を廃止。
 4頂点な面は無くても問題なさそうですしね。

・Frustumにおいて、boundingSphereをサポート。
 たぶんこれは、以前に書いたこの問題の改善だと思われます。

・Object3Dにおいて、rotationとquaternionの相互同期を取るようになった。
 回転が内部的にはクォータニオンに統一されたことに伴う処置のようです。
 これは影響が大きいので後述します。

・Vector3において、get*FromMatrix系メソッドがsetFromMatrix*へ改名。
 なぜ改名?・・・後方互換性が失われました(^_^;)

・CubeGeometryをBoxGeometryへ改名。
 なぜ?(^_^;)

・WebGLRendererからphysicallyBasedShadingを削除。
 シェーダーに影響あり、後述します。

・MeshPhongMaterialからperPixelを削除。
 シェーダーに影響あり、後述します。

・Skeletonを導入。あわせてSkeletonHelperも追加。
 SkinnedMeshのボーンによるスケルトン構造が
 独立したクラスに整理されました。
 スケルトン構造を視覚化するヘルパー関数も追加されました。
 デバッグとかで視覚的に表現できそうですね。

・logarithmic depth buffer を導入。
 LogなZ値を扱えるようになりました。
 カメラの near と far の差が大きいと Z-fighting が起きやすくなりますが、
 それを回避するための機能ですね。
 MMD再生ではとりあえず使う必要はなさそうです。

さて、
シェーダーへの影響について検討してみます。
まずは、perPixelの削除について。
Phongシェーディング(より正確にはBlinn-Phongかな)において、
Lighting処理を頂点レベルで簡易的にやるか、
ピクセルレベル(perPixel)でより正確にやるかということです。
デフォルトでperPixel採用にしたので、このプロパティを削除したようです。
次に、physicallyBasedShadingについて。
これは specular(鏡面様ハイライト) の処理において、
物理的により正しい計算をするかどうかということのようです。
これもデフォルトで採用になったのでプロパティ削除となったようです。
いずれの場合もシェーダーのコストは増えますが、
GPUの性能とか上がってるから良しとしたのかも。
ただMMD的にはリアルスティックにする必要はあまり無いと思うし、
Sphereマップとかで工夫されてたりするみたいなので、
r58でデフォルトだった簡易版で行くことにしました。
従来と見た目が変わるのはどうかなと思ったのと、
シェーダーのコストが上がるのが気になったのも理由です。

そして影響の大きそうな、
Object3Dにおけるrotationとquaternionの相互同期の件。
r58においてはrotationとquaternionは排他使用でした。
useQuaternionプロパティを操作することで、
オイラー角かクォータニオンかを選択する仕組みでした。
しかしr67では相互に同期するようになりました。
つまりrotationを変更するとquaternionも変更されます。
その逆も同様です。
内部的には回転はquaternionに統一したけど、
後方互換性のためにrotationは残しているっぽい?
ただ少々気になるのが変換コスト。
どちらか一方を変更する度に変換計算が行われます。
また、内部的にはクォータニオンになったので、
rotation -> quaternion はまだしも、
quaternion -> rotation は無くても良いような気がします。
そこで、quaternion -> rotation の同期は止めれるように対処しました。
syncEulerプロパティを追加して対応できるようにしました。

そんなこんなで、
どうにかベースを r67 にすることができました。
ようやく本題のDDSに入れます。

ということで、やってみました。
・・・が、しか~し!
なんか gl なエラーがやっぱり出る。

・・・ぐはっΣ( ̄ロ ̄lll)

ベースを上げても関係なかったようです(T_T)
どうやら別な問題らしい。
 ・
 ・
 ・
せっかく r67 に上げたのですが、r58 に比べて
微妙にメモリやシェーダーのコストが増える雰囲気なので、
r58 のままでやり直すことにしました。嗚呼。

再度調査し直した所、
DDSを使ったexampleに答えがありました。
それは textureの minFilter と magFilter でした。
ImageUtils.loadTexture を使った場合は設定されるのですが、
ImageUtils.loadCompressedTexture の場合はそうなっていません。
なんでやねん(^_^;)
デフォルトで設定されない理由はよくわからないのですが、
これを設定しないと gl なエラーが出てしまうようです。
exampleでやってるのを真似して、
以下のようにやったらエラーが出なくなりました。

texture.minFilter = texture.magFilter = THREE.LinearFilter

ただ、これでもまだ問題がありました。
なぜかテクスチャが上下逆に貼られてしまうのです。
ところでこの上下逆問題は以前に指摘されており、
あらかじめテクスチャのV座標を逆転させることで対処しました。
にもかかわらず逆になってしまうのは何故なのか?
調べてみた所、texture.filpY が原因だとわかりました。
初めてこのプロパティの存在に気づいたのですが、
デフォルトでこれは true になっています。
つまり上下逆に貼るようになっていたのを、
さらに逆にすることで正常になるように対処してたことになります。
ところが DDS では flipY が効かないようなのです。
flipY = false に統一して調整しようとも思いましたが、
他で色々影響が出てしまうので止めました。
仕方ないので上下逆転させてから DDS へ変換することで対処しました(^_^;)

さて最後に、
実際にFPSが向上したのかを検証してみました。
結論から言うとほとんど変化なし・・・。
数値的には極々微妙にDDSの方が速かったのですが、ほぼ誤差の範囲。
残念ながら私の環境では差を認識できるような結果にはなりませんでした。
ともあれ、DDSでやってみた結果はこららです。
ちなみに、非DDS版はこららです。
なお、テストでは以下のデータを借用させていただきました。感謝。
モデルはこちら、モデルモーションはこちら、カメラモーションはこちら

WebGL対応のブラウザで見てください。WindowsのChromeで確認しています。PCパワーもそれなりに必要となるかもしれません。反応がない場合は、リロードして再度試してみてください。

やたらとサーバーが重いことがあります・・・。
そんな時は、激しく気長に待ってみてください(^_^;)

shadow などのチェックを全て外し、outline scale をゼロにすると動作的に一番軽くなります。ブラウザの拡張機能を一時的に無効にすると、さらに軽くできるかも。

20140514.001

タグ: ,

コメント / トラックバック 2 件

  1. yomotsu より:

    cube から boxgeometry への変更理由は、mr doob が後悔していたからみたいですよ
    引用> “CubeGeometry” is misnamed, since the method actually creates boxes, not just cubes.
    ソース
    http://www.realtimerendering.com/blog/interview-with-three-js-creator/

    • 管理人 より:

      情報ありがとうございます。

      より一般的なBox(直方体)に対応しているけど、
      名前がCube(立方体)だと誤解を受けそう
      なので改名したということのようですね(^_^)

コメント投稿