Простое любопытство по поводу распределения OpenGL VBO

Я написал простой графический движок с использованием OpenGL и GLSL. До этого момента, когда мне нужно было создать новый узел сцены сетки, я создал VAO, VBO и IBO для каждой сетки. Я загрузил атрибуты вершин для каждого меша следующим образом:

glBufferData(GL_ARRAY_BUFFER, this->GetVerticesByteSize(VERTEX_POSITION)
        + this->GetVerticesByteSize(VERTEX_TEXTURE) + this->GetVerticesByteSize(VERTEX_NORMAL), NULL, this->m_Usage);
    glBufferSubData(GL_ARRAY_BUFFER, 0, this->GetVerticesByteSize(VERTEX_POSITION), &this->m_VertexBuffer[VERTEX_POSITION][0]);
    if (!this->m_VertexBuffer[VERTEX_TEXTURE].empty())
        glBufferSubData(GL_ARRAY_BUFFER, this->GetVerticesByteSize(VERTEX_POSITION),
            this->GetVerticesByteSize(VERTEX_TEXTURE), &this->m_VertexBuffer[VERTEX_TEXTURE][0]);
    if (!this->m_VertexBuffer[VERTEX_NORMAL].empty())
        glBufferSubData(GL_ARRAY_BUFFER, this->GetVerticesByteSize(
            VERTEX_POSITION) + this->GetVerticesByteSize(VERTEX_TEXTURE),
                this->GetVerticesByteSize(VERTEX_NORMAL), &this->m_VertexBuffer[VERTEX_NORMAL][0]);

Но если сцена состоит из большого количества мешей, это неверно для производительности (слишком много изменений состояния). Итак, я решил создать уникальные VAO, VBO и IBO (одноэлементные классы) для всей геометрии моей сцены.

Это можно сделать следующим образом:

Загрузите все атрибуты вершин в определенный класс (назовем его «VertexAttributes») для каждой сетки. После того, как все сетки загружены, мы можем разместить большой буфер вершин в уникальном VBO. Как и выше, я сначала вызываю функцию glBufferData, чтобы выделить всю память с размером всех атрибутов вершины в моей сцене, а затем вызываю функцию glBufferSubData для каждого типа атрибута вершины в цикле.

Но можно ли вызвать glBufferData несколько раз (для каждой сетки) и заполнить VBO во время загрузки сцены (шаг за шагом для каждой сетки). Так это похоже на перераспределение. Можно ли сделать это с помощью OpenGL, или мой первый метод подойдет?


person user1364743    schedule 18.05.2014    source источник
comment
Просто выделить достаточно большой буфер и использовать glMapBufferRange для обновления его частей?   -  person paulm    schedule 18.05.2014
comment
Да, это хорошая идея. Не думал, что это функция. Но с этой техникой я обязан выделить свой буфер, используя glBufferData, с достаточным размером, даже если моя сцена состоит только из маленькой сетки. Но я думаю, что это яснее и быстрее, чем мое первое предложение (загрузка всех атрибутов вершин и после уникального вызова функции glBufferData для выделения на этот раз всей геометрии моей сцены). Но, возможно, есть способ перераспределить VBO. 'glMapBuffer' или 'glMapBufferRange' отображают только выделенную память (я полагаю). Но, возможно, другая функция могла бы перераспределить весь буфер ...   -  person user1364743    schedule 18.05.2014
comment
Не перераспределять в смысле функции C stdlib: realloc (...). В OpenGL нет такой функции, вы можете легко выделить новое хранилище для буферного объекта (и освободить предыдущее хранилище, если в конвейере нет ожидающей команды, которая ссылается на него), но это новое хранилище будет иметь неопределенное содержимое.   -  person Andon M. Coleman    schedule 18.05.2014


Ответы (1)


Но можно ли вызвать glBufferData несколько раз (для каждой сетки) и заполнить VBO во время загрузки сцены (шаг за шагом для каждой сетки). Так это похоже на перераспределение. Можно ли сделать это с помощью OpenGL, или мой первый метод подойдет?

Нет. Каждый раз, когда вы вызываете glBufferData, создается новое хранилище данных (с новым размером, а предыдущее содержимое теряется.

Однако объединение нескольких объектов в одном VBO по-прежнему является допустимой стратегией во многих случаях, особенно если многие из этих объектов, вероятно, будут нарисованы вместе.

Вы не можете динамически изменять размер буферных объектов. Что вы можете сделать, так это предварительно выделить большие буферы и обновить их части. Наличие нескольких доступных и динамически заполняемых буферов разумного размера может быть жизнеспособной стратегией. Обратите внимание, что есть также GL_ARB_copy_buffer (в основном, начиная с GL 3.1, поэтому available), что позволит вам достаточно эффективно копировать на стороне сервера, и вы даже можете имитировать поведение «realloc», выделив новый буфер и скопировав старое содержимое.

Какая стратегия лучше, всегда зависит от ситуации. Если вы часто загружаете или уничтожаете объекты динамически, использование некоторых сложных стратегий выделения буфера и управления может окупиться.

person derhass    schedule 18.05.2014