Я возился с простой концепцией создания 2D стен с помощью C ++ / OpenGL. Каждая стена описывается 4 вершинами и проходит горизонтально или вертикально, а также имеет цвет. Стены переплетаются, если они сталкиваются. Периметры, образованные стенами, заполнены простыми прямоугольниками.
Моя идея состояла бы в том, чтобы хранить данные вершин многих стен в одном VBO. Или несколько для каждого атрибута затем поместить в VAO? Чередование в одном VBO и доступ через VAO? Независимо от того, много стен в одном объекте. Если то, что я храню в хранилище, заканчивается, создайте другое VBO (или то, что я использую) для хранения другой группы стен. Я также хотел, чтобы стены, которые встречаются, например, под прямым углом, разделяли вершины для экономии места.
Однако стены могут изменяться, поэтому вершины можно добавлять, перемещать или удалять в любое время. Это потребует отслеживания свободных блоков в VBO и последующего выделения им данных о стенах по мере необходимости. Это также означало бы, что если у меня есть несколько VBO, две стены, которые имеют общие вершины, должны быть в одном VBO, возможно, создавая все виды головной боли. Но в то же время я не хочу создавать VBO для каждой отдельной стены, которая в большинстве своем является не более чем простой вершинной вещью.
Пример некоторых изменений, происходящих с исходным изображением:
Как эта ситуация обычно обрабатывается? Требуется ли использование моей собственной схемы распределения памяти для работы с VBO, или есть достаточно быстрое решение, которое не требует такой большой работы?
Почему вы думаете, что VBO может не хватить места? Я имею в виду, что для большинства графических процессоров максимальный размер VBO составляет порядка 16-32-64 Мб, это много! (проверьте также Вот)
Если вы можете разместить все свои данные в одном VBO, проблема гораздо проще. Я просто скопировал бы все ваши данные, когда они должны быть изменены (и я считаю, что это случится не часто, если вы не хотите добавлять / удалять стены в каждом кадре).
Если это не приемлемо в вашем случае, я предлагаю вам проверить некоторые популярные реализации из открытых исходных кодов, Вот например, есть GLBufferObject от osg.
Посмотрите на GLBufferObject::compileBuffer()
функция; в вашем случае каждый osg::BufferEntry
может быть группа соединенных стен. Для рендеринга сцены вам придется запросить этот класс, чтобы получить смещения для каждой информации.
Надеюсь это поможет.
Я бы сказал, всякий раз, когда ваши данные изменяются (в том числе при первоначальном создании)
выделить новый буфер для всех вершин (повторно использовать имя VBO, но потерять старый и выделить новое хранилище)
и скопируйте вершины из ваших собственных структур данных в VBO.
Подход существенно зависит от ваших требований.
Я не рекомендую вам реализовывать свой менеджер памяти, если это действительно не нужно. То есть размер вашего буфера превышает несколько мегабайт, и вы часто обновляетесь. Для небольших буферов вы можете хранить и обрабатывать все свои данные на CPU, используя подходящие структуры данных, и просто создать буфер перед рендерингом и передавать все данные в графический процессор. То есть создайте буфер с GL_STREAM_DRAW и обновляйте его полностью каждый кадр.
Если это не так, то реализуйте своего рода диспетчер памяти. Чтобы избежать перемещения данных, используйте вырожденные треугольники (то есть, когда вы удаляете стену, перемещайте вершины стены так, чтобы они составляли треугольник, который будет отбракован растеризатором). Держите список кусков свободных вершин (те, которые составляют вырожденные треугольники) и используйте их для строительства новых стен. Добавление стены не должно быть проблемой. Вы можете использовать любые буферы, какие захотите, но это вряд ли необходимо (недавно я реализовал приложение, которое использовало VBO ~ 300 Мб, оно без проблем работало на всех современных аппаратных средствах).