2016/04/27(水) [n年前の日記]
#1 [prog] three.jsでビルボード
3種類のやり方で実験してみたり。ソースも画像も CC0 / Public Domain ってことで。
ビルボードとは…。 _ビルボードとYビルボードについて - YouTube という動画が分かりやすいかもしれず。
ビルボードとは…。 _ビルボードとYビルボードについて - YouTube という動画が分かりやすいかもしれず。
◎ THREE.PlaneGeometry()を使う方法。 :
THREE.PlaneGeometry(横幅, 縦幅, 横分割数, 縦分割数); を使うと、矩形ポリゴンを1枚作れる。(正確には、三角形ポリゴン2枚で矩形ポリゴンを1枚作ってる状態。) 生成時にサイズを指定することができるので、それぞれ違うサイズで生成できる。割り当てるマテリアルに応じて、光源やフォグを反映させることもできる。
そのままだとビルボードにならないけれど、カメラの位置・角度等を決定した後、レンダリング前にカメラの回転行列(?)を利用して、PlaneGeometry がカメラ側を向いているように回転させてやればビルボードっぽくなるのだとか。
試してみたのが以下。ソースを見たいときは、htmlソースを表示のこと。
_billboard_test1.html (DEMO)
しかし、何故かテクスチャの透過部分・透明部分の見た目がおかしなことに…。カメラから遠くにある PlaneGeometry の透明部分が、背景色・フォグ色で塗り潰されてしまって、透けて見えるはずの地面テクスチャが見えなくなってる。元テクスチャの透明部分は黒なので、透明部分が無効になってるわけではないのだろうけど。
解決策をググってみたら、renderOrder とやらに0以外を指定しておくと良いという話が。
試してみたのが以下。
_billboard_test1_b.html (DEMO)
改善できたように見えるけど、それでもまだ問題が。どうも時々、あちこちの PlaneGeometry が、チラチラする…。
前後関係が変わってチラチラしてるのかと思ったけど、よく見てみると一瞬透明部分が背景色で置き換わってるようで。結局、この不具合に対する解決策は見つからなかった。
そのままだとビルボードにならないけれど、カメラの位置・角度等を決定した後、レンダリング前にカメラの回転行列(?)を利用して、PlaneGeometry がカメラ側を向いているように回転させてやればビルボードっぽくなるのだとか。
// ビルボード相当をカメラを向くように回転 for (var i = 0; i < trees.length; i++) { // trees[i].quaternion.copy(camera.quaternion); trees[i].rotation.setFromRotationMatrix(camera.matrix); }rotation.setFromRotationMatrix(camera.matrix) でカメラ側に向かせることができるけど、quaternion.copy(camera.quaternion) でも同じ効果が得られるらしい。
試してみたのが以下。ソースを見たいときは、htmlソースを表示のこと。
_billboard_test1.html (DEMO)
しかし、何故かテクスチャの透過部分・透明部分の見た目がおかしなことに…。カメラから遠くにある PlaneGeometry の透明部分が、背景色・フォグ色で塗り潰されてしまって、透けて見えるはずの地面テクスチャが見えなくなってる。元テクスチャの透明部分は黒なので、透明部分が無効になってるわけではないのだろうけど。
解決策をググってみたら、renderOrder とやらに0以外を指定しておくと良いという話が。
var geom = new THREE.PlaneGeometry(w, w, 1, 1); var tree = new THREE.Mesh(geom, mat); // これを入れないと透過部分がおかしくなる tree.renderOrder = 1;
試してみたのが以下。
_billboard_test1_b.html (DEMO)
改善できたように見えるけど、それでもまだ問題が。どうも時々、あちこちの PlaneGeometry が、チラチラする…。
前後関係が変わってチラチラしてるのかと思ったけど、よく見てみると一瞬透明部分が背景色で置き換わってるようで。結局、この不具合に対する解決策は見つからなかった。
◎ THREE.Points()を使う方法。 :
パーティクルを描画する時によく使われるらしい、THREE.Points() を使ってみた。2D的なポリゴンを描画してくれるので、カメラの回転行列を利用して云々はしなくていい。光源は反映されないが、フォグを反映させることはできる。
サイズはマテリアル側、THREE.PointsMaterial() の中で指定できる。
試してみたのが以下。
_billboard_test2.html (DEMO)
透過部分・透明部分が、とんでもなくおかしな状態になってる…。また、位置(y座標)の指定も上手くいかない…。どんな座標値を指定すれば地面に設置してくれるのやら…。
通常、パーティクル表現等に THREE.Points() を使う場合は、加算合成などを指定して使うので、透明部分がおかしくなっても問題にならないのだろうけど。この手のビルボードとして使うとなると、なかなか難しいということだろうか…。
サイズはマテリアル側、THREE.PointsMaterial() の中で指定できる。
var mat = new THREE.PointsMaterial({ size: w * 2, map: texTrees[Math.floor(Math.random() * texTrees.length)], transparent: true, fog: true, });複数のテクスチャ種類の使い分けは、Points を1つ作るたびに、対応する Geometry と PointsMaterial を毎回生成して割り当てて解決した。
試してみたのが以下。
_billboard_test2.html (DEMO)
透過部分・透明部分が、とんでもなくおかしな状態になってる…。また、位置(y座標)の指定も上手くいかない…。どんな座標値を指定すれば地面に設置してくれるのやら…。
通常、パーティクル表現等に THREE.Points() を使う場合は、加算合成などを指定して使うので、透明部分がおかしくなっても問題にならないのだろうけど。この手のビルボードとして使うとなると、なかなか難しいということだろうか…。
◎ THREE.Sprite()を使う方法。 :
THREE.Sprite() を使うことでも、2D的なポリゴン描画ができるらしい。これも光源は反映されない。フォグは反映させることができる。
位置とサイズは、THREE.Sprite の position と scale を使って指定できる。
試してみたのが以下。
_billboard_test3.html (DEMO)
これなら大丈夫そう。光源が反映されない点がちょっと気になるけど。
位置とサイズは、THREE.Sprite の position と scale を使って指定できる。
var tree = new THREE.Sprite(mat); tree.position.set(x, y, z); // 位置指定 tree.scale.set(w, w, 1); // サイズ(スケール)指定複数のテクスチャ種類の使い分けは、Sprite を1つ作るたびに、対応する THREE.SpriteMaterial() を毎回生成して割り当てて解決した。
試してみたのが以下。
_billboard_test3.html (DEMO)
これなら大丈夫そう。光源が反映されない点がちょっと気になるけど。
◎ 参考ページ。 :
_three.js webgl - particles - sprites
_three.js webgl - sprites
_javascript - Three.js - billboard effect, maintain orientation after camera pans - Stack Overflow
_Edit fiddle - JSFiddle
_optimization - three.js: how to control rendering order - Stack Overflow
_three.js - Transparent objects in Threejs - Stack Overflow
_transparency - Transparent textures behaviour in WebGL - Stack Overflow
_render - using renderOrder in three.js - Stack Overflow
_three.js webgl - sprites
_javascript - Three.js - billboard effect, maintain orientation after camera pans - Stack Overflow
_Edit fiddle - JSFiddle
_optimization - three.js: how to control rendering order - Stack Overflow
_three.js - Transparent objects in Threejs - Stack Overflow
_transparency - Transparent textures behaviour in WebGL - Stack Overflow
_render - using renderOrder in three.js - Stack Overflow
[ ツッコむ ]
以上です。