Технические особенности OpenGl VBO в C++

Я немного смущен относительно надлежащего использования VBOs в программе OpenGL.

Я хочу создать алгоритм подкачки страниц ландшафта, с помощью карты, названной от 4096x4096 шкала полутонов heightmap как "целая" карта.

Из того, что я читал, каждая вершина, сохраненная в VBO, поднимет 64 байта.

Проблема, которую я имею, состоит в том, что большинство источников указывает, что единственный VBO должен быть между 1-4mb в размере, и меньше VBOs лучше. Все же согласно моим вычислениям, храня каждую вершину взял бы в общей сложности приблизительно гигабайт данных! (4096x4096x64) Это не включает ту каждую вершину, возможно, должен быть сохранен многократно для каждого треугольника.

И при этом это не размещает различные механизмы и людей, которые были бы на этой карте, после того как я получаю часть ландшафта разработанного кода.

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

То, что я действительно хочу знать, что я пропускаю? Я уверен, что делаю некоторый крупный контроль здесь, потому что максимальный размер VBO 4 МБ просто кажется чрезвычайно низким, даже если бы я загружал структуру в 64x64 блоки и различные интерактивные объекты, которые заполнили бы карту также.

Или мои ожидания, какого я могу достигнуть просто нереалистичный? Существует ли лучший метод, доступный мне, что я не знаю? Я смотрю на игры как Забвение или Осадки 3, и некоторым расширяют Безграничную Планету, и наблюдение крупных ландшафтов и удивление, как же это может быть возможно.

Я понимаю, как кодировать, это не мое первое, копаются в OpenGL, но мой первый раз, пытаясь понять и использовать VBOs.

Если кто-либо может пролить некоторый свет в то, где мое понимание VBOs идет не так, как надо, это очень ценилось бы.

5
задан nneonneo 23 March 2013 в 19:32
поделиться

5 ответов

Из того, что я читал, каждая вершина, хранящаяся в VBO, будет занимать 64 байта.

Она может занимать столько байт, сколько вы хотите, в зависимости от формата вершин.
position + normal + texcoords = 4*(3+3+2) = 32 байта на вершину
position + normal + texcoords + tangent vector (для bump) = 4*(3+3+2+3) = 44 байта

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

Идентичные вершины не должны храниться несколько раз. Используйте индексированные примитивы (списки треугольников или полосы треугольников). Свяжите буфер для индицируемых примитивов, затем используйте glDrawElements и glDrawRangeElements . Помните, что в OpenGL можно использовать квады - не обязательно использовать только треугольники.

(4096x4096x64)

Вам не нужно создавать квады для каждого пикселя на карте. Некоторые области совершенно плоские (т.е. высота не меняется), поэтому добавление дополнительных треугольников туда будет пустой тратой ресурсов. Если вы добавите какой-нибудь алгоритм упрощения сетки в готовый ландшафт, вы сможете отказаться от большого количества треугольников. Кроме того, слишком большое количество полигонов приведет к проблемам - треугольник или квадрат должен занимать несколько пикселей. Если есть несколько примитивов, которые должны занимать один и тот же пиксель, результат рендеринга будет немного "шумным". Поэтому нужно учитывать желаемый уровень детализации.

Проблема в том, что большинство источников утверждают, что размер одного VBO должен быть в пределах 1-4мб, и меньше VBO - лучше.

Я бы не стал доверять каждому источнику, особенно в интернете. Многие люди, пишущие учебники, далеко не "эксперты". Другое дело, что в DirectX (не OpenGL) рекомендуется помещать все (т.е. все объекты с совместимым форматом вершин) в один большой статический вершинный буфер (аналог VBO), когда это возможно, и избегать переключения буферов, чтобы уменьшить накладные расходы процессора на вызовы рендеринга. Поэтому совет "VBO не должен быть больше 4 МБ" выглядит для меня крайне подозрительным.

Информация может быть достоверной только если она исходит от разработчика API или от разработчика драйверов (ATI или NVidia). Или когда есть полная уверенность, что автор (учебника или статьи) имеет большой опыт в этой области, а не очередной невежественный разработчик игр. Документам, которые приходят с GDC, Siggraph, ATI, NVidia можно доверять. Некоторые руководства, написанные анонимным "кем-то", должны быть проверены на предмет их соответствия действительности.

В любом случае, что касается производительности, у microsoft было два документа: "Top Issues for Windows Titles" "Performance Optimizations (Direct3D 9)" (DirectX, но некоторые советы могут быть применимы к OpenGL).

Также у NVidia есть коллекция OpenGL ресурсов, которые включают утилиты, связанные с производительностью (GLexpert может быть вам полезен, также есть NVIdia OpenGL SDK и т.д.). В целом, когда вы пытаетесь повысить производительность, пробуйте разные методы и измеряйте результаты вместо того, чтобы слепо следовать чьим-то советам. Посмотрите, сколько дополнительных кадров в секунду вы получите, используя ту или иную технику.

И все же, согласно моим расчетам, хранение каждой вершины займет в общей сложности около гигабайта данных! (4096x4096x64)

Это верно, если вы будете строить всю карту таким образом. Но нет причин загружать всю карту сразу, поэтому вам нужен только видимый кусок карты.

Я смотрю на такие игры, как Oblivion или Fallout 3, и, в некоторой степени, Boundless Planet, вижу массивные ландшафты и удивляюсь, как такое вообще возможно.

Они НЕ загружают все сразу. В любой момент времени загружаются только видимые объекты, текущий "кусок" местности и низкополигональная версия нескольких соседних кусков местности. Игра хранит только те объекты, которые используются в данный момент или будут использоваться в ближайшее время. Она постоянно получает данные с жесткого диска.

9
ответ дан 18 December 2019 в 16:35
поделиться

Если вы вводите / выводите данные на страницу, вам понадобится по крайней мере 4 VBO на случай, если вы визуализируете около границы «четырех углов». Но по мере того, как вы перемещаетесь, вы можете заменять данные в этих четырех VBO вместо того, чтобы создавать / выпускать их все время. Для этого метода вы должны использовать один из «динамических» флагов использования, чтобы OpenGL знал, что данные могут измениться, но каждый раз они будут использоваться более одного раза.

0
ответ дан 18 December 2019 в 16:35
поделиться

Размер вершины определяет, сколько места она займет в буфере вершин. Если ваша вершина состоит только из 3D позиции, то на одну вершину у вас будет 12 байт.

Это не считая того, что каждую вершину может потребоваться хранить несколько раз для каждого треугольника.

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

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

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

Я уверен, что совершаю здесь какую-то огромную ошибку, потому что максимальный размер VBO в 4мб кажется чрезвычайно низким, даже если бы я загружал текстуру блоками 64x64, а также различные интерактивные объекты, которые будут заполнять карту.

Если вы используете вершины, которые имеют 64 байта, то 4 Мб дает вам 65536 вершин. (256x256) Этого должно быть достаточно для всего, а если вам нужно больше вершин, вы разделите их между несколькими вершинными буферами.

Отказ от ответственности: Лично я только недавно начал использовать OpenGL и не смогу помочь вам ответить на вопросы, связанные с OpenGL.

1
ответ дан 18 December 2019 в 16:35
поделиться

Я подозреваю, что вы не используете карты высот по назначению. У вас есть изображение 4096x4096, которое представляет собой массив пикселей , не предназначенный для использования в качестве вершин . Весь смысл хранения высот в текстуре (также известной как карта высот) заключается в том, чтобы избежать такого уровня детализации в геометрии (то есть в буферах вершин).

Точная техника использования зависит от вашего контекста. Если ландшафт предназначен только для визуализации, я бы рекомендовал представить его на одном квадрате ( 4 вершины ) и использовать такие шейдеры, как карты освещения , отображение смещения или отображение параллакса . Если он предназначен для некоторого взаимодействия с другими объектами (например, с персонажами, идущими по нему), тогда некоторая геометрия в порядке - но определенно не 4096x4096. Вот один из способов адаптивной выборки карты высот по ее локальному уровню детализации.

1
ответ дан 18 December 2019 в 16:35
поделиться

Как уже упоминалось, размер вершины в VBO зависит от вашей вершины формат, поэтому нет фиксированного формата и, следовательно, размер не фиксирован. Статистика по оптимальным размерам VBO, как правило, устаревает, не ожидайте, что у вас получится правильно с первого раза, просто поиграйте с размером и профилем, на это у вас не уйдет так много времени.

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

То, что вы думали о каком-то алгоритме разбиения по страницам, совсем неплохо, есть один хорошо известный алгоритм рендеринга ландшафта, который использует этот подход, который называется Chunked LOD . Этот алгоритм использует отдельный поток подкачки для визуализации статического ландшафта вне ядра.

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

1
ответ дан 18 December 2019 в 16:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: