Почему объекты Vertex Buffer улучшают производительность?

10

Исходя из моего базового понимания, объект буфера вершин работает примерно так (псевдокод):

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

line (0, 0) -> (1, 0)
line (1, 0) -> (1, 1)
line (1, 1) -> (0, 1)
line (0, 1) -> (0, 0)

Использование VBO, если я правильно понимаю, загрузит вершины в VBO.

define VBO
load (0,0) -> VBO
load (1,0) -> VBO
load (1,1) -> VBO
load (0,1) -> VBO
load (0,0) -> VBO

Затем вы можете выполнить одну команду рисования.

draw VBO vertices

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

Как они улучшают производительность?

Этан Бирляйн
источник

Ответы:

11

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

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

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

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

porglezomp
источник
10

Есть два шага, которые делают VBO более эффективным, чем непосредственный режим.

  1. Непосредственный режим ( glBegin / glEnd , glVertex * и т. Д.) Означает, что в каждом кадре вы ложите вершины, атрибут для каждого атрибута (позиция, нормаль, цвет и т. Д.), Драйверу, который затем переформатирует их и, наконец, отправляет весь пакет как команда для GPU. Это много вызовов функции на вершину в каждом кадре.
    (Обратите внимание, что немедленный режим устарел начиная с OpenGL 3.0 и полностью удален из 3.2 .)

  2. Используя массивы вершин (см. GlDrawArrays , glDrawElements , glVertexPointer и т. Д.), Вы можете дать драйверу все сразу и избавить его от необходимости переформатирования вершин. Вы фактически заменяете несколько вызовов функций на вершину всего лишь несколькими вызовами для всей сетки. Но вам все равно нужно делать это один раз за кадр.

  3. Vertex Buffer Object или VBO (см. GlGenBuffers , glBindBuffer и т. Д.) Идут на шаг дальше и сохраняют данные на стороне графического процессора: вы отправляете их только один раз, а затем просто обращаетесь к ним с помощью дескриптора. Вы экономите пропускную способность, не посылая одни и те же данные снова и снова в каждом кадре.

Жюльен Геро
источник
6

Используя интерфейс непосредственного режима (например, старый стиль OpenGL glBegin () / glEnd () / glVertex ()), вы эффективно вытягиваете данные для драйвера по одному фрагменту за раз. Затем он должен взять этот отдельный фрагмент данных, переформатировать его и передать его аппаратному обеспечению (что в наши дни означает помещение его в буфер команд).

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

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

Эндрю Сидвелл
источник