6

概要

私は現在、Three.jsで3Dタイル状の六角形ボードを作成しています。芸術的および機能的な理由から、タイルはそれぞれ独自のメッシュであり、基本的な(変更されていない)ジオメトリと、そのマテリアルに生成されたマップの配列(変位、拡散、法線)で構成されています。

テクスチャマップを追加すると、FPSの低下に気づき始め、ソースを調べるようになりました。私は15x15のゲームボードを持っています。つまり、フレームごとに225の個別のメッシュがレンダリングされています。当時、各メッシュはデザインが不十分なため215面で構成されていたため、シーンには48,375面が含まれていました。

パフォーマンスの問題を解決できると考えて、メッシュを再設計して、シーン全体で合計6,750面の30面のみを含むようにしました。驚異的な改善。顔を86%減らしても、パフォーマンスにほとんど影響がないことに失望しました。

そこで、パフォーマンスの低下の原因を正確に突き止めることにしました。抽象化されたテスト環境を設定し、3x10の平面のグリッドを使用しました(自分のモデルと同じように、30の面を与えるため)。さまざまなグリッドサイズ(メッシュ数)を試し、さまざまな複雑さのマテリアルを適用しました。これが私が見つけたものです:

材料試験

// /---------------------------------------------------\
// |      Material       |  15x15  |  20x20  |  25x25  |
// |---------------------|---------|---------|---------|------\
// | Flat Lambert Color  |  60FPS  |  48FPS  |  30FPS  | -00% |
// | Lambert Diffuse     |  57FPS  |  41FPS  |  27FPS  | -10% |
// | Blank Shader        |  51FPS  |  37FPS  |  24FPS  | -20% |
// | Full Shader (-H)    |  49FPS  |  32FPS  |  21FPS  | -30% |
// | Full Shader (+H)    |  42FPS  |  28FPS  |  19FPS  | -37% |
// \----------------------------------------------------------/
//                       |   -00%  |   -33%  |   -55%  |
//                       \-----------------------------/

行:

  • MeshLambertMaterial({color})私のベースラインでした
  • MeshLambertMaterial({map})パフォーマンスが約10%低下しました
  • ShaderMaterial()デフォルト設定を使用すると、パフォーマンスが約20%低下しました
  • ShaderMaterial()ディフューズマップを使用すると、パフォーマンスが約30%低下しました。
  • ShaderMaterial()Diffuse + Normal + Displacementマップを使用すると、37%のパフォーマンスヒットが発生しました

列:

  • 15x15(225メッシュ)が私のベースラインでした
  • 20x20(400メッシュ)は33%のパフォーマンスヒットを受けました
  • 25x25(625メッシュ)は55%のパフォーマンスヒットを受けました

あらすじ

そのため、使用しているシェーダーと適用しているマップから大きなヒットがあったことを知りました。ただし、「モノ」の量からははるかに大きなヒットがあります。これが面なのかメッシュなのかわからなかったので、別のテストを実行しました。ベースラインマテリアル(MeshLambertMaterial({ color: red }))を使用して、2つの変数をテストすることにしました。辺の数とメッシュの数です。これが私が見つけたものです:

顔/メッシュカウントテスト

// 15x15 (225)  Meshes @ 30 Faces =   6,750 Faces   = 60 FPS
// 20x20 (400)  Meshes @ 30 Faces =  12,000 Faces   = 48 FPS
// 25x25 (625)  Meshes @ 30 Faces =  18,750 Faces   = 30 FPS
// 30x30 (900)  Meshes @ 30 Faces =  27,000 Faces   = 25 FPS
// 40x40 (1600) Meshes @ 30 Faces =  48,000 Faces   = 15 FPS
// 50x50 (2500) Meshes @ 30 Faces =  75,000 Faces   = 10 FPS

// 15x15 (225) Meshes @ 100 Faces =  22,500 Faces   = 60 FPS
// 15x15 (225) Meshes @ 400 Faces =  90,000 Faces   = 60 FPS
// 15x15 (225) Meshes @ 900 Faces = 202,500 Faces   = 60 FPS

シンポシス

これは、関係する面の数がフレームレートにほとんど影響しないことを非常に決定的に示しているようです。むしろ、シーンに描画される個々のメッシュの量によって、実質的にすべてのパフォーマンスドラッグが作成されます。何がそのような遅れを正確に引き起こしているのかわかりません。メッシュごとに大量のオーバーヘッドがあると思います。おそらく、このオーバーヘッドの一部を排除する方法はありますか?

考慮事項

私はすでに自分のジオメトリをマージすることを検討しました。これにより、フレームレートの低下がほぼ完全に解消されます。ただし、この記事の冒頭で述べたように、各タイルは個別に翻訳可能、回転可能、スケーラブル、その他の方法で変更可能である必要があります。私の知る限り、これはマージされたジオメトリでは不可能です。

また、デフォルトでマージされたジオメトリを使用し、タイルを変更する関数が呼び出されたときにジオメトリ/シーンを再作成することも検討しました。ただし、このアプローチには2つの問題があります。

  1. ボード上に200〜400の個別のメッシュがあり、マージされている場合、処理に1000ミリ秒以上かかる可能性があり、目立った視覚的なスタッターが発生する可能性があります。
  2. すべてのタイルを同時に「揺さぶる」または「ぐらつく」可能性があるような大きな効果は、現在のボードと同じように遅れ、それらを実装する理由はありません。

私は、このパフォーマンスへの影響を回避しようとするのではなく、それを排除する解決策を見つけたいと思っています。

質問

それは私の質問に私をもたらします:大量の個々のメッシュをレンダリングするためのより効率的な方法はありますか?

4

2 に答える 2

5

私はすでに自分のジオメトリをマージすることを検討しました。これにより、フレームレートの低下がほぼ完全に解消されます。ただし、この記事の冒頭で述べたように、各タイルは個別に翻訳可能、回転可能、スケーラブル、その他の方法で変更可能である必要があります。私の知る限り、これはマージされたジオメトリでは不可能です。

もちろんそうだ。頂点が属するタイルを識別する整数である頂点属性を追加します。次に、頂点シェーダーで計算できるものに応じて、タイルを個別に移動できます。

変換など、タイルごとに個別のデータが必要な場合は、それをテクスチャにロードし、タイルインデックスを使用してテクスチャから値を検索できます。また、テクスチャが(歪んだ)コピーのように見えるように配置することもできます。簡単なデバッグのための16進グリッド!

「シェイク」効果のようなものについては、テクスチャさえ必要ありません。現在の時刻を示す一様変数を追加し、タイルインデックスによって変更される方法でシェイクを計算するだけです。

于 2012-10-12T00:55:15.133 に答える
1

テクスチャマップを追加すると、FPSの低下に気づき始めました...

一般に、レンダリングの状態変化を最小限に抑える必要があります。テクスチャやシェーダーなどを変更するには、GPUに新しい情報を送信する必要があります。それは安価な操作ではありません。

試すことができる「簡単な」ことは、メッシュをマテリアルでソートしてレンダリングすることです。ツリートラバーサルでメッシュをレンダリングする場合、代わりにマテリアルでレンダリングするようにレンダリングコードを再構築する必要があるため、「シンプル」を使用します。

状態の変化を最小限に抑えるためにレンダリングを最適化できる他のさまざまな方法については、ChristerEricsonからのこの投稿を参照してください。

于 2012-10-11T23:57:03.363 に答える