3

私は現在 OpenGL を学習しており、スプライト シートから画面にスプライトを描画したいと考えています。ただし、これを正しい方法で行っているかどうかは確信しています。

私がやりたいのは、Terraria 風のタイルで世界を構築することです。つまり、私の世界を構築するすべてのタイルは 1x1 ですが、後で 2x1、1x2、2x2 などのエンティティが必要になる可能性があります。

私が今行っていることは、タイルの変換マトリックスとそのバッファーへのポインターを含む「Tile」という名前のクラスがあることです。非常に簡単です:

Tile::Tile(glm::vec2 position, GLuint* vbo)
{
    transformMatrix = glm::translate(transformMatrix, glm::vec3(position, 0.0f));
    buffer = vbo;
}

次に、タイルを描画するときに、バッファーをバインドし、シェーダーの UV 座標と頂点位置を更新します。その後、タイルの変換マトリックスをシェーダーに渡し、glDrawElements を使用して描画します。

glEnableVertexAttribArray(positionAttrib);
glEnableVertexAttribArray(textureAttrib);

for(int i = 0; i < 5; i++) 
{
    glBindBuffer(GL_ARRAY_BUFFER, *tiles[i].buffer);

    glVertexAttribPointer(positionAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
    glVertexAttribPointer(textureAttrib, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (void*)(2 * sizeof(GLfloat)));

    glUniformMatrix4fv(transformMatrixLoc, 1, GL_FALSE, value_ptr(tiles[i].transformMatrix));
    glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
}

glDisableVertexAttribArray(positionAttrib);
glDisableVertexAttribArray(textureAttrib);

これをもっと効率的に行うことはできますか?1x1 タイル用に 1 つのバッファー、2x1 タイル用に 1 つのバッファーなどを用意して、Tile クラスに UVpos と UVsize を含めて、それらをシェーダーに送信するだけでよいと考えていましたが、どうすればよいかわかりません。そうするだろう。

1x1 用に 1 つ、2x1 用に 1 つのバッファーで説明したことは、はるかに高速になるように聞こえます。

4

1 に答える 1

1

これをより効率的に行うことができますか?

私はあなたがそれをより効率的にすることができないと思います。クワッドごとにバッファオブジェクト全体をバインドしています。次に、マトリックスをアップロードします。クワッドごと

タイルマップの描画(およびエンティティではなくマップのみ)が通常機能する方法は、表示されている画面のタイルの一部を含むバッファーオブジェクトを作成することです。空のスペースは透明なタイルとしてレンダリングされます。次に、画面のその領域のすべてのタイルを、すべて1回の描画呼び出しでレンダリングします。その領域のすべてのタイルに1つのマトリックスを提供します。

通常、そのような表示領域がいくつかあるので、変更されたときにその領域のタイルを簡単に更新できます。画面外に出た領域は、画面上に出た領域に再利用されるため、新しいタイルデータでそれらを埋めます。

于 2013-01-20T21:00:00.777 に答える