Я пишу экспериментальное приложение, в котором я визуализирую 100 фрагментов кубов 16x16x16, используя VBO. Я делаю это, потому что дюжина людей безмерно хвалила VBO и говорила мне, что он намного лучше работает, чем списки отображения по частям, которые я использую в своей настоящей игре в стиле Minecraft.

Это был болезненный процесс, когда я пытался адаптировать множество плохо написанных руководств, посвященных только одному кубу/треугольнику, во что-то, что может справиться с объемом рисования, который мне нужен. Я до сих пор не уверен, что VBO лучше подходят для моей игры, чем списки отображения.

По большей части я, наконец, подправил код так, чтобы мои чередующиеся данные VBO строились только один раз (при загрузке фрагмента), а затем каждый render вызов, идентификатор буфера привязан и glDrawArrays называется.

Я постепенно увеличиваю количество блоков/фрагментов в этом экспериментальном приложении, чтобы посмотреть, как работает производительность. В реальной игре ему придется обрабатывать 16x16x128 блоков в каждом чанке, при этом загружается не более 20×20 чанков. Примерно 60% из них будут сплошными отрендеренными блоками, то есть примерно 8 миллионов блоков. Это без особых проблем отображается с использованием метода списка отображения, с которого я начал.

#2 Minecraft с нуля на C++ — VAO и VBO

Однако, несмотря на то, что сейчас производительность рендеринга VBO находится на приемлемом уровне, я не могу сгенерировать радиус 10 фрагментов, не достигнув предела памяти:

Exception in thread «main» java.lang.OutOfMemoryError: Direct buffer memory at java.nio.Bits.reserveMemory(Bits.java:658) at java.nio.DirectByteBuffer.(DirectByteBuffer.java:123) at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:306) at org.lwjgl.BufferUtils.createByteBuffer(BufferUtils.java:60) at org.lwjgl.BufferUtils.createFloatBuffer(BufferUtils.java:110) at com.helion3.opengl.rendering.TextureQuadRenderer.(TextureQuadRenderer.java:25) at com.helion3.opengl.shapes.Chunk.(Chunk.java:13) at com.helion3.opengl.shapes.World.(World.java:18) at com.helion3.opengl.Game.start(Game.java:90) at com.helion3.opengl.Launcher.main(Launcher.java:19)

Я вполне уверен, что мои буферы настроены с нужным количеством счетчиков. Я звоню:

BufferUtils.createFloatBuffer( через 192 плавает на куб (3 вершины, 3 цвета, 2 координаты текстуры, умноженные на шесть граней и 4 вершины на грань), умноженные на 4096 — количество блоков в чанк-тесте.

Теперь в реальной игре я не визуализирую грани блоков, которые не подвергаются воздействию воздуха, но даже если я делаю это в этом тестовом приложении, я все равно визуализирую только блоки размером 16x16x16.

Как я могу лучше управлять памятью VBO? Мой тест ВБО код рендеринга приложения, код фрагмента

В какой момент VBO сияют так, как все продают их? ржу не могу

PS Думаю, теперь я углублюсь в создание экземпляров, посмотрим, как это поможет.

Если вы хотите использовать VBO с эффективным использованием памяти, перестаньте хранить свои цвета в виде значений с плавающей запятой. GLubyte использует 1/4 хранилища. Также я не уверен, почему у вас заканчивается память Java; VBO выделяют память в адресном пространстве, управляемом драйвером дисплея. VRAM во всех смыслах и целях. Если вы правильно используете VBO, вы не должны заметно увеличивать объем памяти, которой сама Java должна управлять для вашего приложения, это означает освобождение исходного ByteBuffer после отправки данных в GL. — Andon M. Coleman

Я освобождаю исходный ByteBuffer после привязки данных, а для цветов я просто следил за тем, как все примеры демонстрируют это, хотя все чередуется, поэтому все находится в одном буфере с плавающей запятой (на кусок) — helion3

Хм, видимо, я был только clear используя оригинальный ByteBuffer, установив для него значение null Кажется, проблема с памятью решается, но производительность с фрагментами 20×20 снова падает до ужасной. Сейчас я нахожусь в масштабе, где мне действительно следует отключить рендеринг всего куба, если он не выставлен. Довольно скоро у меня будет моя оригинальная игра. лол — helion3

Да, у меня есть претензии к людям, которые пишут все эти чередующиеся руководства по VBO на Java. В C/C++/ObjC они используют struct , состоящие из смеси GLfloat и GLubyte , так и должно быть. Вы все еще можете смешивать и сочетать GLubyte и GLfloat в чередующемся VBO в Java, но вам нужно использовать ByteBuffer и упакуйте в него свои компоненты с плавающей запятой по 4 байта каждый и цветные компоненты по 1 байту каждый. Конечно, это сложнее, но это правильный способ обработки массивов вершин с цветом. — Andon M. Coleman

На данный момент у меня тысячи споров с авторами учебников. Слишком много расплывчатых инструкций, которые на самом деле не учитывают реальное использование. Я поищу хороший учебник по объединению чисел с плавающей запятой/байтов в буфере байтов. Использует ли он byteBuffer.asFloatBuffer() для значений с плавающей запятой? — helion3

Читайте также:  Как поставить миску в Майнкрафте на пол

1 ответы

Теперь в реальной игре я не визуализирую грани блоков, которые не подвергаются воздействию воздуха, но даже если я делаю это в этом тестовом приложении, я все равно визуализирую только блоки размером 16x16x16.

Это очень хорошо. Я просто упомянул об этом, потому что, прежде всего, распространенная ошибка, которую люди делают при написании рендереров в стиле Minecraft, заключается в попытке отправить OpenGL. все блоков (хуже, если они оказывать торговый центр). Вместо этого вы должны определить, какие поверхности действительно видны, и оставить только их в VBO.

Здесь помогает использование пространственной структуры подразделения. Мир, похожий на Minecraft, просто пахнет Octree, которые могут тривиально хранить реальную вещь. (Это для других людей, столкнувшихся с этим вопросом и ответом здесь).

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

При создании экземпляров вам нужно всего 4 целых числа на блок, чтобы полностью описать его (3 для позиции, 1 для поверхности, которую вы загружаете из GL_TEXTURE_2D_ARRAY). Целые числа предпочтительнее, потому что они бывают меньшего размера (единственный недостаток в том, что старые графические процессоры не могут эффективно их обрабатывать). Скажем, один куб соответствует 1 м³.

Затем 16-битное целое число дает вам мир (65536 м)³. Также вам вряд ли понадобится более 256 видов поверхностей для игры в стиле Minecraft. Поэтому используйте 8-битное целое число для представления этого. Затем, когда вы рассматриваете только видимые поверхности, то есть блоки, большая часть вашего объема не должна находиться в VBO.

Это может реально сэкономить память. Переход от 32-битных чисел с плавающей запятой к 16-битным целым числам экономит 50% памяти. Использование одного 8-битного целого числа для индекса материала вместо 3 × 32-битного цвета с плавающей запятой сокращает ваши требования к памяти до 1/12.

Чтобы еще больше снизить нагрузку на рендеринг, вы можете использовать параллельность всех кубов в мире. Это позволяет невероятно легко исключить скрытые поверхности даже из обработки: существует 8 + 6 основных направлений, с которых можно смотреть на куб: 8, где видны 3 грани, имеющие общий угол, и 6 направлений, где видна только поверхность, на которую вы смотрите. прямо видно. Довольно легко определить основные плоскости в мире, где каждый случай применим с текущей точки зрения. Таким образом, у вас есть 14 вариантов базового шаблона куба, и вы делаете вызовы экземпляров в каждом подтоме для определенного случая. Октодерево снова помогает вам выбрать, какие экземпляры получат какой вариант.

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

В общем, вы хотите, чтобы ваши данные были хорошо выровнены и объединены (хотя с текущими многоканальными архитектурами памяти отдельные макеты данных также могут обеспечить довольно хорошую производительность). Однако ваш шаблон доступа не должен, так сказать, «прыгать повсюду». Держите ваши доступы красиво сгруппированными. Это основная причина, по которой списки отображения могут превзойти VBO: содержимое постоянно, и драйвер может преобразовать их содержимое в оптимально выровненную и упорядоченную структуру. Вам придется поэкспериментировать с этим.

Чтобы дать вам представление о том, что делают современные игровые движки: в недавнем отчете DICE говорится, что в грядущей игре «Battlefield 4» один кадр даже самых сложных сцен генерируется не более чем 2000 API рисования. звонки. Это действительно низкий показатель.

ответ дан 08 дек ’13, 03:12

Источник: stackovergo.com

Что означает настройка «Использовать VBO»?

Что означает настройка «Использовать VBO»?

В снимке 14w29b в меню «Настройки видео» появилась новая опция «Использовать VBO»:

В обновлении моментального снимка говорится, что включение «Vertex Buffer Objects» должно увеличить ваш FPS в среднем на 5-10%.

Я ищу простое объяснение того, что VBO делают визуально и как они работают.

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

В немедленном режиме (я думаю, что это случай по умолчанию в minecraft), когда вы хотите отобразить, скажем, квадрат:

Вы должны вводить следующие команды в каждом кадре (в псевдокоде)

Читайте также:  Чем отличаются forge и optifine версии Майнкрафта

begin drawing draw line from (0,0) to (1,0) draw line from (1,0) to (1,1) draw line from (1,1) to (0,1) draw line from (0,1) to (0,0) end drawing

Для одного квадрата это немного, но в сцене могут быть миллионы вершин, и у них может быть больше атрибутов (цвет, нормаль и т. Д.). Это много данных, которые нужно отправлять в графический процессор каждый кадр.

Используя VBOS, вы сначала загрузите все данные вершин в память графического процессора. Псевдокод может выглядеть так:

create VBO load (0,0) into VBO load (1,0) into VBO load (1,1) into VBO load (0,1) into VBO load (0,0) into VBO

Код OpenGL вернет вам «имя» для этого VBO (ненулевое целое число без знака iirc). Затем вы можете ссылаться на это, когда хотите нарисовать квадрат. Таким образом, для каждого кадра вам нужно выполнить только одну команду рисования:

draw vertices in VBO

Возможно, вам придется настроить состояние рисования так, чтобы оно использовало пары вершин для линий, но для каждого дополнительного VBO вам потребуется только один дополнительный вызов рисования. Фактически, для геометрии статического уровня (вероятно, не применимо в случае Minecraft) вы можете объединить все эти вершины в один массивный VBO, если у вас достаточно памяти графического процессора.

Удивительно, что ускорение всего 5-10%. Вероятно, это из-за геометрии динамического уровня.

VBO — это аббревиатура от Vertex Buffer Object.

Из статьи в Википедии

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

Простыми словами

В частности, в Minecraft он предлагает увеличение производительности на ~ 10% при включении

Он делает это за счет уменьшения нагрузки на ваш процессор и оперативную память и переназначения ее памяти графического процессора, это рекомендуется только в том случае, если у вас есть нормальная видеокарта.

  • Я заметил, что вы просто скопировали первый абзац статьи «Вертикальный буферный объект» в Википедии. Что касается повышения производительности на 10%, где ваши источники и что вы подразумеваете под производительностью? Частота кадров? Использование процессора?
  • 1 это то, что делает VBO, что касается увеличения на 10%, взятого из примечаний к обновлению снимка.
  • Использование ОЗУ, если вы читаете то, что я опубликовал, в нем говорится, что он переназначает его на память графического процессора, облегчая нагрузку на другие ресурсы, вы должны использовать это только в том случае, если у вас есть соответствующая видеокарта, чтобы это не влияло на производительность этого
  • Калеб, в конце концов, я точно ответил на ваш вопрос, как вы его задали, я не понимаю, в чем ваша проблема
  • Я могу читать Википедию, но это не значит, что я понимаю используемые сложные термины. Я ищу ответ от человека, который понимает, что делает VBO, и может объяснить это простым языком. Я отредактирую свой вопрос, чтобы сделать его более понятным.

Это существенно увеличивает скорость за счет снижения нагрузки на процессор и системную память (RAM). Вместо этого используйте память видеокарты, чтобы повысить производительность.

Источник: ru.bikiniclinic.net

Что для более эффективного рендеринга вокселов: готовый VBO или геометрический шейдер?

Учитывая довольно статичный массив вокселей, что более эффективно: использование ЦП для предварительной генерации VBO для рендеринга граней вокселей (без учета более продвинутых форм рендеринга, например, марширующих кубов) или использование геометрического шейдера в графическом процессоре для генерации лица на лету?

Я не беспокоюсь об обновлении смены вокселей, но, конечно, это преимущество GPU-версии, поскольку вам не нужно перестраивать VBO. Кроме того, подход GS чувствует себя немного более современным 🙂

С другой стороны, я не рассматривал детали того, как GS на самом деле работает с конвейером растеризации в современных графических процессорах. Выводит ли он вершины в своего рода потоковый кеш или вершины записываются в обычную память графического процессора между ними? Если это последнее, то генерация на лету может уменьшить доступную полосу пропускания и вычислительную мощность по сравнению с остальными задачами с графическим процессором, и тогда было бы выгоднее делать это на процессоре.

Читайте также:  Как выглядит зомби мутант в Майнкрафте

Я имею в виду сцену типа Minecraft, где под вокселем вы подразумеваете мир блоков, которые на самом деле визуализируются с использованием полигонов:

Если вы используете геометрический шейдер, вам будет трудно избежать ровно трех граней (или чего-то еще) на воксель.

Если у вас есть много смежных блоков, которые имеют одинаковую текстуру, вы можете использовать мозаику текстур, чтобы иметь гораздо меньше треугольников в вашей (вырожденной) полосе в подходе VBO. Я имею в виду, что если есть хороший большой плоский участок 6×6 вокселей травы, вы можете нарисовать всю вершину всего за 2 треугольника, а не за 64.

При подходе GS вы не можете выполнять тривиальный отбор граней, перекрытых соседними вокселями, что также очень просто при подходе VBO.

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

Я использовал отдельные VBO для каждой из 6 граней — вам, очевидно, нужно всего лишь нарисовать не более 3 из них. Это прекрасно согласуется с различными текстурами, обычно используемыми в верхних частях вокселей в стиле Minecraft. Потому что для каждого набора нормальное и таковое тогда одинаково.

С использованием вертикально-мозаичных растровых изображений в атласе с GL_REPEAT горизонтальной осью и с поворотными на 90 градусов версиями растровых изображений в одном и том же атласе я обнаружил, что могу рисовать огромное количество явно разных блоков, используя один и тот же VBO в одном вызове. В примере с площадью травы 6х6 я бы разбил это на 12 треугольников, поскольку я повторял только одно измерение в моем атласе.

Я в основном заставлял это работать на самом низком уровне интегрированных графических чипов и мобильных устройств, где GS — это просто то, о чем я могу мечтать, играя однажды.

Вам нужно нарисовать не более 3 граней на каждый воксел, но вам может потребоваться нарисовать разные грани для каждого вокселя в зависимости от точки обзора, так что оптимизация не так проста, верно? Готовый VBO будет содержать более одного вокселя. Если ваша точка зрения находится между вокселями, вы увидите восточную сторону одного и западную сторону другого. Единственный способ, которым это могло бы помочь, — это то, что вы можете тривиально отбирать фактические грани, обращенные назад, но в худшем случае вы по-прежнему визуализируете 5 из 6 сторон в группе вокселей. Если ваша точка обзора находится за пределами осевых границ VBO, то вам нужно только визуализировать 3 стороны.

Пятно на Бьорне, это выполнимо. (Но я создаю VBO для блоков по мере необходимости и пересматриваю то, что я построил, когда камера движется, вместо того, чтобы постоянно иметь весь мир в VBO; так что у меня есть естественное время, чтобы сделать этот выбор)

Как насчет третьего варианта, использующего инстансированные массивы? По сути, вы рисуете множество блоков (сделанных из простого 8-вершинного куба) одним вызовом отрисовки, выбирая позиции (и другие данные) в качестве атрибутов для каждого экземпляра из VBO Voxel-data ( glVertexAttribDivisor я уверен, используя OpenGL) У DX это тоже есть). Это может быть быстрее, чем подход геометрического шейдера, хотя код приложения (не шейдер) должен быть довольно похожим, поскольку я помню, что геометрические шейдеры имеют репутацию медленных, хотя у меня нет опыта работы с ними (или создания экземпляров), так как я до сих пор сижу на 2.1 аппаратно.

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

Источник: qastack.ru