1

たくさんの四角形を描きたいです。

今、私には問題があります。描画は正常に動作し、高速ですが、クワッドのコンテナーとして std::vector を使用していて、本当に遅いです。XNA から来て、spriteBatch のようなものを作成して、DrawQuad() を呼び出して特定のクワッドをリストに追加し、最後に End() を呼び出してすべてのクワッドを描画できるようにする必要があると考えました。

私の現在のコードは、通常、次のようなものをコンソールに出力します。

DrawQuad(): 77
End(): 0

何度も何度も。

Main.cpp (sf::Clock はSFMLの時計クラスです)

sf::Clock time;
for (int y = 0; y < 100; y++)
    for (int x = 0; x < 100; x++)
        renderer.DrawQuad("A", Vector2<GLfloat>(-1.0f + x * 0.02f, -1.0f + y * 0.02f));
std::cout << "DrawQuad(): " << time.getElapsedTime().asMilliseconds() << std::endl;

レンダラー.cpp:

void TextRenderer::DrawQuad(string text, Vector2<GLfloat> position)
{
    //TOP LEFT
    vertexBufferVector.push_back(position.X);
    vertexBufferVector.push_back(position.Y);

    //TOP RIGHT
    vertexBufferVector.push_back(position.X + 0.02f);
    vertexBufferVector.push_back(position.Y);

    //BOTTOM RIGHT
    vertexBufferVector.push_back(position.X + 0.02f);
    vertexBufferVector.push_back(position.Y + 0.02f);

    //BOTTOM LEFT
    vertexBufferVector.push_back(position.X);
    vertexBufferVector.push_back(position.Y + 0.02f);

    int elementCount = elementBufferVector.size() / 6; 

    elementBufferVector.push_back(elementCount * 4);
    elementBufferVector.push_back(elementCount * 4 + 1);
    elementBufferVector.push_back(elementCount * 4 + 2);

    elementBufferVector.push_back(elementCount * 4 + 2);
    elementBufferVector.push_back(elementCount * 4 + 3);
    elementBufferVector.push_back(elementCount * 4);
}

void TextRenderer::End()
{
    sf::Clock time;

    GLfloat* vertexArray = &vertexBufferVector[0];
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertexBufferVector.size(), vertexArray, GL_STATIC_DRAW);

    GLint* elementArray = &elementBufferVector[0];
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLint) * elementBufferVector.size(), elementArray, GL_STATIC_DRAW);

    glDrawElements(GL_TRIANGLES, elementBufferVector.size(), GL_UNSIGNED_INT, 0);

    vertexBufferVector.clear();
    elementBufferVector.clear();

    std::cout << "End(): " << time.getElapsedTime().asMilliseconds() << std::endl;
}

自分が何をしているかを知っている人は、これをどのように解決しますか? 10000クワッドは実際には問題になりません。

これをすべて書いた後、ループを (100, 100) から (1000, 100) に増やしたところ、描画に 4 ~ 5 ミリ秒かかりました。いや…と思ってます。

4

1 に答える 1

0

これは死んでいるので、質問に答えるだけで、誰かの助けになるかもしれません。

ベクトルを使用する代わりに、サイズを設定した配列を使用することにしました。これにより、100000 クワッド (テクスチャも含む) の合計レンダリング時間が平均 ~3.260ms に短縮されました。

私の .h は次のようになります。

const int MAX_BUFFER_SIZE = 1000;
const int MAX_VERTEX_BUFFER_SIZE = MAX_BUFFER_SIZE * 16;
const int MAX_ELEMENT_BUFFER_SIZE = MAX_BUFFER_SIZE * 6;

...

GLint vertexBufferArrayInserts;
GLfloat vertexBufferArray[MAX_VERTEX_BUFFER_SIZE];
GLint elementBufferArray[MAX_ELEMENT_BUFFER_SIZE];

そして、.cpp ファイルの関連部分:

void TextRenderer::DrawQuad(Vector2<GLfloat> position)
{
    if(vertexBufferArrayInserts == MAX_BUFFER_SIZE)
        End();

    //TOP LEFT
    vertexBufferArray[vertexBufferArrayInserts * 16] = position.X;
    vertexBufferArray[vertexBufferArrayInserts * 16 + 1] = position.Y;
    vertexBufferArray[vertexBufferArrayInserts * 16 + 2] = 0.0f;
    vertexBufferArray[vertexBufferArrayInserts * 16 + 3] = 0.0f;

    //TOP RIGHT
    vertexBufferArray[vertexBufferArrayInserts * 16 + 4] = position.X + 16.0f;
    vertexBufferArray[vertexBufferArrayInserts * 16 + 5] = position.Y;
    vertexBufferArray[vertexBufferArrayInserts * 16 + 6] = 24.0f / 512.0f;
    vertexBufferArray[vertexBufferArrayInserts * 16 + 7] = 0.0f;

    //BOTTOM RIGHT
    vertexBufferArray[vertexBufferArrayInserts * 16 + 8] = position.X + 16.0f;
    vertexBufferArray[vertexBufferArrayInserts * 16 + 9] = position.Y + 16.0f;
    vertexBufferArray[vertexBufferArrayInserts * 16 + 10] = 24.0f / 512.0f;
    vertexBufferArray[vertexBufferArrayInserts * 16 + 11] = 32.0f / 512.0f;

    //BOTTOM LEFT
    vertexBufferArray[vertexBufferArrayInserts * 16 + 12] = position.X;
    vertexBufferArray[vertexBufferArrayInserts * 16 + 13] = position.Y + 16.0f;
    vertexBufferArray[vertexBufferArrayInserts * 16 + 14] = 0.0f;
    vertexBufferArray[vertexBufferArrayInserts * 16 + 15] = 32.0f / 512.0f;


    //ELEMENT BUFFER
    elementBufferArray[vertexBufferArrayInserts * 6] = vertexBufferArrayInserts * 4;
    elementBufferArray[vertexBufferArrayInserts * 6 + 1] = vertexBufferArrayInserts * 4 + 1;
    elementBufferArray[vertexBufferArrayInserts * 6 + 2] = vertexBufferArrayInserts * 4 + 2;
    elementBufferArray[vertexBufferArrayInserts * 6 + 3] = vertexBufferArrayInserts * 4 + 2;
    elementBufferArray[vertexBufferArrayInserts * 6 + 4] = vertexBufferArrayInserts * 4 + 3;
    elementBufferArray[vertexBufferArrayInserts * 6 + 5] = vertexBufferArrayInserts * 4;

    vertexBufferArrayInserts++;
}

void TextRenderer::End()
{
    glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat) * vertexBufferArrayInserts * 16, vertexBufferArray);

    glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLint) *  vertexBufferArrayInserts * 6, elementBufferArray);

    glDrawElements(GL_TRIANGLES, vertexBufferArrayInserts * 6, GL_UNSIGNED_INT, 0);

    vertexBufferArrayInserts = 0;
}

そして、これが私がそれを計った方法です:

sf::Clock timer;
renderer.Begin(projMatrix);

for (int y = 0; y < 100; y++)
    for(int x = 0; x < 1000; x++)
        renderer.DrawQuad(Vector2<GLfloat>(16.0f * x, 16.0f * y));

renderer.End();

avgDrawTime += timer.getElapsedTime().asMicroseconds();
drawCalls++;

if(drawCalls % 100 == 0)
    std::cout << avgDrawTime / drawCalls << std::endl;
于 2013-04-13T10:47:35.070 に答える