0

LWJGL と Java 1.6 を使用して 2D RPG を作成しています。ここまでで、タイルの ArrayList (すべてのタイルの基本コードとのインターフェイス) を保持する 'World' クラスと、Spritesheet を使用する GrassTile クラスができました。

Immediate モードを使用して 64x64 の GrassTiles のグリッドを描画する場合、約 100 FPS を取得し、ArrayList 内の各タイルから .draw() メソッドを呼び出すことでこれを行います。 )。そこで、VBO を使用した方がよいと聞き、基本的なチュートリアルを入手して、それらを .draw() メソッドに実装しようとしました。

テクスチャの特定の領域のみを VBO にバインドする方法がわからないので (テクスチャ全体は単に glBindTexture() になります)、色のみで使用してみました。2 番目の問題に進みます。+20 FPS (合計 120) しか得られませんでしたが、これは実際には期待したものではありません。何か間違ったことをしていると思います。また、ArrayList 内で反復しながら、GrassTile ごとに 1 つの VBO を作成しています。すべてのタイルを単一の FloatBuffer 内に単純にスローできるため、それはちょっと間違っていると思います。

では、同様のジオメトリをより良い方法で描画するにはどうすればよいでしょうか? また、テクスチャの特定の領域のみを VBO にバインドするにはどうすればよいでしょうか?

4

2 に答える 2

2

これが鍵です:

ArrayList 内で反復しながら、GrassTile ごとに 1 つの VBO を作成しています。

これをしないでください。一度 VBO を作成し、必要に応じて更新します。テクスチャ、VBO、シェーダーの作成は、OpenGL の最も遅い使用方法です。問題のあるフレームレートが得られるのも不思議ではありません。各フレームで O(n) 回実行しています。

単一の FloatBuffer 内のすべてのタイルを単純にスローすることはできない['t?]ので、それはちょっと間違っていると思います。

描画呼び出しをバッチ処理する場合にのみ、パフォーマンスが向上します。つまり、タイルを描画するときは、 1 つのVBOで一度にすべてのタイルを描画する必要があります。

//Initialize
Make a single VBO (or two: one for vertex, one for texture
coordinates, whatever--the key point is O(1) VBOs).
Fill your VBO with ALL of your tiles' data.

//Main loop
while (true) {
    Draw the VBO with a single draw call,
    thus drawing all your tiles all at once.
}
于 2012-08-10T21:05:22.170 に答える
2

では、どうすれば同様のジオメトリをより良い方法で描画できますか...

@Ian Mallettが説明したように; すべての頂点データを単一の頂点バッファー オブジェクトに入れます。これにより、1 回の呼び出しでマップをレンダリングできます。マップが 1000 倍大きくなった場合、画面に表示されている頂点のみを描画するカメラ ソリューションを実装することをお勧めしますが、これは、非常に大きなマップを計画している場合に後で発生する問題です

...そして、テクスチャの特定の領域のみを VBO にバインドするにはどうすればよいですか?

テクスチャ全体のみをバインドできます。マップしたいテクスチャの特定の領域を指す必要があります。

すべてのテクスチャ座標は、特定の頂点に関連しています。すべてのタイルは 4 つの頂点に関連しています。ゲーム内の一般的なタイルは同じテクスチャ共有するため、「タイル マップ」という名前が付けられています。それを利用してください。すべてのタイル テクスチャをテクスチャ シートに配置し、そのテクスチャ シートをバインドします。作成する新しい「タイル」ごとに、エリアが空中、草、地面のいずれであるかを確認し、意図するものに対応するテクスチャの部分をポイントします。

ピクセル単位のテクスチャ領域が 100x100 であるとします。グラウンド領域は、左下隅から 15x15 です。上記のロジックに従って、以下に示すサンプル コードを説明します。

// The vertexData array simply contains information
// about a tile's four vertices (or six 
// vertices if you draw using GL_TRIANGLES).

mVertexBuffer.put(0, vertexData[0]);
mVertexBuffer.put(1, vertex[1]);
mVertexBuffer.put(2, vertex[2]);
mVertexBuffer.put(3, vertex[3]);
mVertexBuffer.put(4, vertex[4]);
mVertexBuffer.put(5, vertex[5]);
mVertexBuffer.put(6, vertex[6]);
mVertexBuffer.put(7, vertex[7]);
mVertexBuffer.put(8, vertex[8]);
mVertexBuffer.put(9, vertex[9]);
mVertexBuffer.put(10, vertex[10]);
mVertexBuffer.put(11, vertex[11]);

if (tileIsGround) {
   mTextureCoordBuffer.put(0, 0.0f);
   mTextureCoordBuffer.put(1, 0.0f);

   mTextureCoordBuffer.put(2, 0.15f);
   mTextureCoordBuffer.put(3, 0.0f);

   mTextureCoordBuffer.put(4, 0.15f);
   mTextureCoordBuffer.put(5, 0.15f);

   mTextureCoordBuffer.put(6, 0.15f);
   mTextureCoordBuffer.put(7, 0.0f);
} else { /* Other texture coordinates. */ }

あなたは実際に解決策を書きました。唯一の違いは、テクスチャ座標データを GPU にアップロードする必要があることです。

于 2012-08-11T15:47:29.200 に答える