Проблемы с использованием VBO для рендеринга вершин - OpenGL - PullRequest
5 голосов
/ 12 августа 2011

Я передаю функции моих вершинных массивов в VBO, чтобы увеличить скорость моего приложения.

Вот моя оригинальная функция рендеринга массива вершин:

void BSP::render()
{
    glFrontFace(GL_CCW);

    // Set up rendering states
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &vertices[0].x);

    glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vertices[0].u);

    // Draw
    glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, indices);

    // End of rendering - disable states
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}

Отлично сработало!

Теперь я перемещаю их в VBO, и моя программа фактически заставила мою видеокарту перестать отвечать на запросы. Настройки моих вершин и индексов точно такие же.

Новая настройка:

vboId настроен в bsp.h примерно так: GLuint vboId [2];

Я не получаю ошибку, когда просто запускаю функцию createVBO ()!

void BSP::createVBO()
{

    // Generate buffers
    glGenBuffers(2, vboId);

    // Bind the first buffer (vertices)
    glBindBuffer(GL_ARRAY_BUFFER, vboId[0]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // Now save indices data in buffer
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

}

И код рендеринга для VBOS. Я уверен, что это здесь. Просто хочу отобразить то, что в VBO, как я делал в массиве вершин.

Рендер:

void BSP::renderVBO()
{
    glBindBuffer(GL_ARRAY_BUFFER, vboId[0]);         // for vertex coordinates
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboId[1]); // for indices

    // do same as vertex array except pointer
    glEnableClientState(GL_VERTEX_ARRAY);             // activate vertex coords array
    glVertexPointer(3, GL_FLOAT, 0, 0);               // last param is offset, not ptr

    // draw the bsp area
    glDrawElements(GL_TRIANGLES, numVertices, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));

    glDisableClientState(GL_VERTEX_ARRAY);            // deactivate vertex array

    // bind with 0, so, switch back to normal pointer operation
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}

Не уверен, что это за ошибка, но я почти уверен, что у меня неправильная функция рендеринга. Хотелось бы, чтобы по этому вопросу был более унифицированный учебник, так как есть много онлайн, но они часто противоречат друг другу.

Ответы [ 3 ]

2 голосов
/ 12 августа 2011

Кроме того, что сказал Миро (GL_UNSIGNED_BYTE должно быть GL_UNSIGNED_SHORT), я не думаю, что вы хотите использовать numVertices, но numIndices, как в вашем вызове не-VBO.

glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);

В противном случае ваш код выглядит вполне корректно, и если это не решит вашу проблему, возможно, ошибка в другом месте.

И, кстати, вещь BUFFER_OFFSET(i) обычно является просто определением для ((char*)0+(i)), так что вы также можете просто передать байтовое смещение напрямую, особенно когда оно равно 0.

РЕДАКТИРОВАТЬ: Просто заметил еще один. Если вы используете точные структуры данных, которые вы используете для версии без VBO (которую я предполагал выше), то вам, конечно, нужно использовать sizeof(Vertex) в качестве параметра шага в glVertexPointer.

0 голосов
/ 12 августа 2011

Как вы объявляете вершины и индексы ?

Параметр size для glBufferData должен быть размером буфера в байтах, и если вы передадите sizeof (вершины) , он вернет общий размер объявленного массива (а не только то, что выделено).

Попробуйте что-то вроде sizeof (вершина) * numVertices и sizeof (индексы [0]) * numIndices вместо.

0 голосов
/ 12 августа 2011

Если вы передаете те же данные в glDrawElements, когда вы не используете VBO, и те же данные в буфер VBO.Тогда параметры немного отличаются, без FBO вы использовали GL_UNSIGNED_SHORT и с FBO вы использовали GL_UNSIGNED_BYTE.Поэтому я думаю, что вызов VBO должен выглядеть так:

glDrawElements(GL_TRIANGLES, numVertices, GL_UNSIGNED_SHORT, 0);

Также посмотрите этот урок , там очень хорошо объяснены буферы VBO.

...