Как использовать VBO OpenGL 3.x для рендеринга динамического мира?

Хотя, похоже, очень мало актуальных ссылок для самого OpenGL 3.x, фактическая манипуляция с низким уровнем OpenGL относительно прямолинейна. Однако у меня возникают серьезные проблемы, пытаясь даже концептуализировать, как можно манипулировать VBOs, чтобы сделать динамичный мир.

Очевидно, что способы немедленного режима старого не применимы, но оттуда куда я могу пойти? Я пишу какую-то структуру сцены, а затем конвертирую ее в набор вершин и stream, который должен быть в VBO, как я могу хранить данные о переводе? Если да, то каким образом этот код выглядит разумным?

В принципе действительно неуверенный, как продолжить.

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

    Тем не менее, я предполагаю, что у вас есть сцена, состоящая из нескольких жестких объектов, которые перемещаются относительно друг друга. В этом случае используйте один VBO для каждого объекта и укажите GL_STATIC_DRAW_ARB использования GL_STATIC_DRAW_ARB . Затем вы можете установить преобразование модели для каждого экземпляра объекта и визуализировать его с помощью одного вызова рисования для каждого экземпляра.

    Эмпирическое правило (на ПК) должно выдавать не более одного обратного вызова на МГц вашего ЦП. Это грубая оценка, но в этом есть доля правды. Не беспокойтесь о том, чтобы положить несколько независимых объектов в один VBO или другие трюки производительности, если вы останетесь ниже этого предела.

    Короткий ответ:

    Используйте glMapBufferRange и обновляйте поддиапазон, который нуждается в модификации.

    Длительный ответ:

    Трюк состоит в том, чтобы сопоставить уже существующий буфер с glMapBufferRange , а затем отобразить только диапазон, который вам нужен. Учитывая эти предположения:

    • Ваша geometry использует морфинг для каждой вершины
    • Количество вершин для моделей является постоянным во время анимации.

    Затем вы можете использовать glMapBufferRange для обновления только изменяющихся частей и оставить остальную часть данных в покое. Полные загрузки с помощью glBufferData медленны, как черепаха, потому что они удаляют старый магазин памяти и выделяют новый. Это в дополнение к загрузке новых данных. glMapBufferRange позволяет читать или записывать существующие данные, не выделяет и не освобождает.

    Однако, если вы используете анимацию скелета, скорее передайте вершинные преобразования как матрицы 4×4 на вершину вершинного шейдера и выполните вычисления там. Пер-вершинные данные, конечно, указаны с помощью glVertexAttribPointer .

    Кроме того, помните, что вы можете читать данные текстуры в вершинном шейдере и что OpenGL 3.1 представил несколько новых вызовов рисования экземпляров; glDrawArraysInstanced и glDrawElementsInstanced . Комбинированные могут использоваться для конкретных запросов. Т.е. вы можете делать вызовы с примерами, используя одни и те же данные геометрии, но отправляйте позиции или любые требуемые данные в виде вершин в виде текстур или массивов текстур. Это может избавить вас от смешивания и сопоставления наборов данных массива вершин.

    Представьте себе, хотите ли вы отображать 100 экземпляров одной и той же модели, но с разными позициями или цветовой схемой. Или даже текстурные карты.

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

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

    В качестве оптимизации вы могли бы объединить несколько моделей в один VBO, а затем передавать ненулевые смещения при совершении обратных вызовов; это вытаскивает правильную модель из VBO. Также желательно объединить несколько вызовов рисования в один обратный вызов, но это невозможно, если они должны иметь независимые преобразования. (На самом деле это возможно в определенных ситуациях, если вы используете инстанс или смешение вершин, но я предлагаю сначала извлечь из него основы.)