2012-03-17 25 views
1

私はwebglを使って小さなゲームに取り組んでいます。この試合では、私は、多くの(100以上の)樹木からなる何らかの種類の森林を持っています。私はいくつかの異なるツリーモデルしか持っていないので、私はそれらを表示する前に、これらのモデルを別の方法で回転させ、スケーリングします。それらを表示するために、すべての木の上にモーメントIループでwebglを使用してバッチを実装する方法は?

for (var tree in trees) { 
    tree.display(); 
} 

のような木のdisplay()方法が見えますが:多くのツリーオブジェクトが同じtreeModelオブジェクトを共有するので、私

display : function() { // tree 
    this.treeModel.setRotation(this.rotation); 
    this.treeModel.setScale(this.scale); 
    this.treeModel.setPosition(this.position); 
    this.treeModel.display(); 
} 

モデルを表示する前に、モデルの回転/スケール/位置を設定する必要があります。回転/スケール/位置の値はツリーごとに異なります。

treeModelの表示方法は、すべてのGLのものを行います。

display : function() { // treeModel 
    // bind texture 
    // set uniforms for projection/modelview matrix based on rotation/scale/position 
    // bind buffers 
    // drawArrays 
} 

すべてのツリーモデルが同じシェーダを使用しますが、異なるテクスチャを使用することができます。

1つのツリーモデルはいくつかの三角形から構成されているため、すべてのツリーを1つのVBOに結合し、1つのdrawArrays()コールでフォレスト全体を表示したいと考えています。

いくつかの仮定が簡単に数字の話を作るために:

  • を表示するには、250本の木があり、5種類の木のモデルがあり
  • すべてのツリーモデルは、50個の三角形

質問があります私は持っています:

  • 現在、私は50 * 3 * 8 (position + normal + texCoord) * floatSizeバイトの5つのバッファを持っています。 1つのvboですべてのツリーを表示したいとき、私は250 * 50 * 3 * 8 * floatSizeバイトサイズのバッファを持っています。ツリーごとに異なる位置の値があるので(ツリーモデルの位置値とツリー位置/スケール/回転)、インデクスバッファを使うことはできません。これは正しいのですか?それとも、インデックスバッファを使ってバッファサイズを少なくとも少しでも減らす方法はありますか?多分これを最適化する他の方法がありますか?

  • ツリーモデルの異なるテクスチャをどのように扱うか?私はすべてのテクスチャを異なるテクスチャユニットにバインドできますが、現在表示されているフラグメントにどのテクスチャを使用するべきかシェーダ内でどのように決定できますか?

  • 実行時に新しいツリー(または他の種類のオブジェクト)をこのバッファに追加する場合は、次のようにします。新しいバッファを作成してコンテンツをコピーする必要はありますか? glMapBufferを使って新しい値を追加できないと思います。これは正しいです?

答えて

4

インデックス要素バッファは、長さが65535以下の属性にしか到達できないため、代わりにdrawArraysを使用する必要があります。それは通常大きな損失ではありません。

GL.bufferSubDataを使用して、バッファの最後にツリーを追加できます。

テクスチャが妥当なサイズ(128x128または256x256など)であれば、それらを1つの大きなテクスチャにマージして、UVコードですべてを扱うことができます。そうでない場合は、頂点がどのテクスチャに属しているかを示す別の属性を追加したり、頂点シェーダに条件を設定したりすることができます。シェーダの条件はかなり遅いことを忘れないでください。

現在のソリューションに固執する場合は、必ず同じテクスチャを使用してレンダリングされるようにツリーを並べ替えるようにしてください。状態の切り替えを維持することが必須です。

+0

+1 for texture atlas。また、私はWebGL(Mac OSでのChromeの実装は少なくとも、WebGL自体で可能)は配列テクスチャをサポートしているとは思わない。 –

+0

複数のテクスチャを1つにマージするとよいでしょう。私はこれを調べます。また、私はインデックスが65kに制限されていることを知らなかった。良い情報、ありがとう。 – micha

+0

インデックスされた要素に使用されるデータ型(Uint16Array)のため、65kに制限されています。 – MikaelEmtinger

1

現在のアプローチはそれほど悪くありません。私は言うだろう:あなたがいくつかの壁に当たるまで、それに固執する。

50個の三角形は、すでに単一のdrawElements/drawArrays呼び出しに対して妥当なバッチサイズです。最適ではないが、それほど悪くない。だから、すべての木のために、場所、テクスチャ、ユニフォームの形などのパラメタを変更してください。次に、各ツリーの描画呼び出しを行います。また、合計250のdrawElements呼び出しはそれほど悪くない。

私は使用されているすべてのツリージオメトリバリアントを含む単一のVBOを使用します。私は実際に木々をビルディングブロックに分割して、追加された品種のためにそれらを再結合できるようにしました。また、各ツリーに対して、drawArraysまたはdrawElementsを呼び出す前にVBOに適切なオフセットを設定します。

また、各ツリーの非常に安価な視界カリングを行うことができることを忘れないでください。

2

いくつかの考え:あなたはあなたの世界で木を植えたら

  1. 、あなたはそれを修正するのですか?それはまったくアニメーション化されますか?それとも静的なジオメトリですか?本当に静的な場合は、常に各ツリーの複数のコピーで単一のバッファを構築することができます。ツリーを追加するときは、まずインスタンスのワールド変換を頂点に適用します(Javascriptで)。三角形ストリップを使用している場合は、縮退ポリゴンを使用してツリーをリンクすることができます。
  2. 独自の擬似インスタンス描画をロールバックすることができます。
    1. インスタンスIDを配列バッファにエンコードします。同じツリーインスタンスの一部であるすべての頂点に対して、これを同じ値に設定するだけです。私はES GLSLで浮動小数点の頂点属性を持つことはできないことを思い出しているようです(多分Chromeの制限です)ので、浮動小数点数としてintにする必要があります。それは浮動小数点数として入ってくるので、三角形全体に補間されているという事実に対処しなければならないでしょう。したがって、値は微妙な変動を伴いますが、直近の整数フィックスに丸めるだけです。
    2. 個別のテクスチャ(データテクスチャと呼ぶ)を使用して、すべてのインスタンスごとの情報をエンコードします。頂点シェーダで、現在の頂点のインスタンスIDを見て、それを使ってデータテクスチャのテクスチャ座標を計算します。現在の頂点を変換するために必要なものを取り出し、適用します。私はこれを「依存テクスチャの読み込み」と呼びますが、それは一般的にはパフォーマンス上の問題を引き起こす可能性があるからですが、パフォーマンスの問題を解決するのに役立つジオメトリをバッチ処理するのに役立つかもしれません。あなたが興味を持っているなら、それを試して何が起こるか見る必要があります。
  3. 実際のインスタンス化された描画をサポートするための拡張機能が必要です。
+0

#1:現時点では木々は完全に静止しています。しかし、私は後ですべてを変えずにそれらをアニメートするオプションが必要です。アニメーションは私の現在のアプローチのもう一つの問題だと思います。 "従属テクスチャを読む"アイデアをありがとう。私はこれを確かに調べます。 – micha

関連する問題