1

頂点配列を使用して、LWJGL で約 2097152 個のキューブをレンダリングしようとしています (一度にすべてではありません)。パフォーマンスを約 2 FPS から約 60 FPS に向上させるために、さまざまなタイプのポリゴン カリングを実装しました。このプロジェクトを通して、私はイミディエート モード レンダリングを使用してきましたが、そろそろアップグレードの時期だと思います。ここで、頂点配列の出番です。

私は VBO を使いたくないので、今のところ VAO を試しています。実用的な(または効率的な)レンダリング方法を理解できないようです。残念ながら、何を試しても即時モードよりも FPS が悪くなります。フレームごとに、ポリゴンが表示されているキューブごとに FloatBuffer をロードし、共通の頂点配列メソッドを使用してそれらを描画します。このセットアップでは、Immediate モードを使用してポリゴンをカリングしない場合よりも FPS が少なくなるため、頭痛の種になります。

私は何か間違ったことをしていると思います。優秀で意欲的な OpenGL/LWJGL プログラマーの中で、より効果的かつ効率的な方法でこれを行う方法を知っている人はいますか?

これがレンダリング用の私のコードです(あまり混乱しないように切り捨てられています):

for(int z = 0; z < chunk.bpc; z++) {
for(int y = 0; y < chunk.bpc; y++) {
    for(int x = 0; x < chunk.bpc; x++) {
        if(((z == chunk.bpc - 1 || z == 0) || (y == chunk.bpc - 1 || y == 0) || (x == chunk.bpc - 1 || x == 0)) 
            && chunk.data[(x * chunk.bpc + z) * chunk.bpc + y] == i) {

                List<Float> vertices = new ArrayList<Float>();

                float xp = x + locX, yp = y + locY, zp = z + locZ;

            if(z == chunk.bpc - 1 && chunk.z$ == null) {
                vertices.add(xp); vertices.add(yp); vertices.add(zp + size);
                vertices.add(xp + size); vertices.add(yp); vertices.add(zp + size);
                vertices.add(xp + size); vertices.add(yp + size); vertices.add(zp + size);
                vertices.add(xp); vertices.add(yp + size); vertices.add(zp + size);
            }

            if(z == 0 && chunk.z_ == null) {
                vertices.add(xp); vertices.add(yp); vertices.add(zp);
                vertices.add(xp); vertices.add(yp + size); vertices.add(zp);
                vertices.add(xp + size); vertices.add(yp + size); vertices.add(zp);
                vertices.add(xp + size); vertices.add(yp); vertices.add(zp);
            }

            if(y == chunk.bpc - 1 && chunk.y$ == null) {
                vertices.add(xp); vertices.add(yp + size); vertices.add(zp);
                vertices.add(xp); vertices.add(yp + size); vertices.add(zp + size);
                vertices.add(xp + size); vertices.add(yp + size); vertices.add(zp + size);
                vertices.add(xp + size); vertices.add(yp + size); vertices.add(zp);
            }

            if(y == 0 && chunk.y_ == null) {
                vertices.add(xp); vertices.add(yp); vertices.add(zp);
                vertices.add(xp + size); vertices.add(yp); vertices.add(zp);
                vertices.add(xp + size); vertices.add(yp); vertices.add(zp + size);
                vertices.add(xp); vertices.add(yp); vertices.add(zp + size);
            }

            if(x == chunk.bpc - 1 && chunk.x$ == null) {
                vertices.add(xp + size); vertices.add(yp); vertices.add(zp);
                vertices.add(xp + size); vertices.add(yp + size); vertices.add(zp);
                vertices.add(xp + size); vertices.add(yp + size); vertices.add(zp + size);
                vertices.add(xp + size); vertices.add(yp); vertices.add(zp + size);
            }

            if(x == 0 && chunk.x_ == null) {
                vertices.add(xp); vertices.add(yp); vertices.add(zp);
                vertices.add(xp); vertices.add(yp); vertices.add(zp + size);
                vertices.add(xp); vertices.add(yp + size); vertices.add(zp + size);
                vertices.add(xp); vertices.add(yp + size); vertices.add(zp);
            }

            float[] verts = new float[vertices.size()];
            for(int a = 0; a < verts.length; a++) {
                verts[a] = vertices.get(a);
            }

            FloatBuffer cubeBuffer = BufferUtils.createFloatBuffer(verts.length);
            cubeBuffer.put(verts);
            cubeBuffer.flip();

            GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);

            GL11.glVertexPointer(3, 0, cubeBuffer);

            GL11.glDrawArrays(GL11.GL_QUADS, 0, verts.length / 3);

            GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
        }
    }
}
}

(これらの変数のいくつかは無視してください。異なるポリゴンをカリングするだけです)

そのため、これを行うためのより効率的な方法があるかどうかはわかりませんが、ある場合は、いくつかのポインターを取得できれば幸いです。前もって感謝します!ああ、そして...

レンダリング方法に非常に問題があります。

4

2 に答える 2

1

フレームごとにジオメトリを再生成しないでください。内部レンダリングループでの動的メモリ割り当ては、一般的に悪い考えです。

チャンクが表示されたとき、およびそのチャンクが変更された場合/変更されたときに、チャンクのジオメトリを1回生成します。

おそらく、LRUキャッシュを使用してジオメトリを格納し、非表示のチャンクがキャッシュからゆっくりとパージされるようにします。

于 2013-01-27T19:31:35.543 に答える
1

LWJGL と VAO について読んだことはありますが、個人的には使用したことがありませんが、VBO は常にうまく機能してくれました。しかし、コード スニペットを見ると、このスニペットをすべてのフレームで呼び出しているようです。したがって、本質的には、フレームごとにデータを変更し、新しいバッファーを作成し、データをバッファーから転送してから、バッファー内のデータをレンダリングします。フレームごとに新しいバッファを作成するのはコストがかかるため、これを一度行ってからバッファを再利用してください。また、フレームごとにデータを変更している場合、VAO と VBO では、即時モードよりもパフォーマンスが向上しない可能性があります。その理由は、即時モードでは各フレームのデータを GPU メモリに転送してレンダリングするためです。この転送にはコストがかかります。一方で、

于 2013-01-27T19:37:25.527 に答える