mieki256's diary



2016/04/27(水) [n年前の日記]

#1 [prog] three.jsでビルボード

3種類のやり方で実験してみたり。ソースも画像も CC0 / Public Domain ってことで。

ビルボードとは…。 _ビルボードとYビルボードについて - YouTube という動画が分かりやすいかもしれず。

THREE.PlaneGeometry()を使う方法。 :

THREE.PlaneGeometry(横幅, 縦幅, 横分割数, 縦分割数); を使うと、矩形ポリゴンを1枚作れる。(正確には、三角形ポリゴン2枚で矩形ポリゴンを1枚作ってる状態。) 生成時にサイズを指定することができるので、それぞれ違うサイズで生成できる。割り当てるマテリアルに応じて、光源やフォグを反映させることもできる。

そのままだとビルボードにならないけれど、カメラの位置・角度等を決定した後、レンダリング前にカメラの回転行列(?)を利用して、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)
billboard_test1_ss.png

しかし、何故かテクスチャの透過部分・透明部分の見た目がおかしなことに…。カメラから遠くにある 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)
billboard_test1_b_ss.png

改善できたように見えるけど、それでもまだ問題が。どうも時々、あちこちの PlaneGeometry が、チラチラする…。

前後関係が変わってチラチラしてるのかと思ったけど、よく見てみると一瞬透明部分が背景色で置き換わってるようで。結局、この不具合に対する解決策は見つからなかった。

THREE.Points()を使う方法。 :

パーティクルを描画する時によく使われるらしい、THREE.Points() を使ってみた。2D的なポリゴンを描画してくれるので、カメラの回転行列を利用して云々はしなくていい。光源は反映されないが、フォグを反映させることはできる。

サイズはマテリアル側、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)
billboard_test2_ss.png

透過部分・透明部分が、とんでもなくおかしな状態になってる…。また、位置(y座標)の指定も上手くいかない…。どんな座標値を指定すれば地面に設置してくれるのやら…。

通常、パーティクル表現等に THREE.Points() を使う場合は、加算合成などを指定して使うので、透明部分がおかしくなっても問題にならないのだろうけど。この手のビルボードとして使うとなると、なかなか難しいということだろうか…。

THREE.Sprite()を使う方法。 :

THREE.Sprite() を使うことでも、2D的なポリゴン描画ができるらしい。これも光源は反映されない。フォグは反映させることができる。

位置とサイズは、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)
billboard_test3_ss.png

これなら大丈夫そう。光源が反映されない点がちょっと気になるけど。

参考ページ。 :


以上です。

過去ログ表示

Prev - 2016/04 - Next
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project