WedX - журнал о программировании и компьютерных науках

OpenGL: Как Vertex Buffer управляет своей памятью?

Я изучаю OpenGL, и я пытаюсь понять вещи правильно. Если мое понимание неверно в каком-либо пункте, поправьте меня.

Введение

Итак, допустим, у нас есть треугольник. Этот треугольник имеет свои вершины. Скажем, у этих вершин задана только позиция — ни цвета, ни чего-либо еще. Эти вершины передаются шейдерам с помощью буфера — назовем его VB (VBO в учебниках).

Шейдеры следующие:

Вершинный шейдер:

#version 330 core
layout (location = 0) in vec3 aPos;

void main()
{
    gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}

Фрагментный шейдер:

#version 330 core
out vec4 FragColor;

void main()
{
    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}

VB представляет собой неформатированный массив данных. Например, если бы мы хотели передать в этот буфер 3 однобайтовых значения (0, 255, 16), данные выглядели бы так:

00FFF0

Однако шейдеры не умеют читать данные, поэтому нам нужно проинструктировать их, сказав, что есть что. Для этого мы используем Vertex Array Objects. Назовем наш объект Vertex Array VA.

Для передачи данных в буфер используется glBufferData. При вызове функции следующим образом:

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

Мы сообщаем OpenGL, что хотим буферизовать sizeof(vertices) элементов из массива vertices в буфер, привязанный к GL_ARRAY_BUFFER для статического рисования.

Затем мы сообщаем VA, как использовать данные следующим образом:

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);

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

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

Вопрос

Однако что, если мы хотим изменить одну вершину после того, как мы уже передали данные в буфер?

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

Если он перезапишет его, как нам передать другие данные, скажем, цвета, не перезаписывая позиции?

Если нет, то как VA узнает, что данные, на которые он указывает, больше не актуальны?

28.05.2021


Ответы:


1

Данные буфера можно обновить с помощью glBufferSubData (или Сопоставление). glBufferData создает новое хранилище данных с неизменным размером. Таким образом, вы не можете добавлять дополнительные данные в буфер. Сначала необходимо создать достаточно большой буфер.
Однако вы можете создать отдельный буфер для дополнительных атрибутов.

28.05.2021

2

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

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

Если он перезапишет его, как нам передать другие данные, скажем, цвета, не перезаписывая позиции?

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

Это будет выглядеть примерно так (обратите внимание на параметр stride, установленный на 0, который сообщает драйверу, что данные не чередуются):

size_t coord_start = 0;
size_t normal_start = coord_start + coord_data_len;
size_t color_start = normal_start + normal_data_len;

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)coord_start );
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)normal_start );
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*)color_start );

Таким образом, когда вы вызываете glBufferSubData() для обновления диапазона памяти, содержащего цвета, вы оставите координаты и данные нормалей в покое.

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

Если нет, то как VA узнает, что данные, на которые он указывает, больше не актуальны?

Здесь все становится довольно сложно. На бумаге это проблема водителя, и вам не стоит об этом беспокоиться.

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

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

28.05.2021
Новые материалы

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

Работа с цепями Маркова, часть 4 (Машинное обучение)
Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

Учебные заметки: создание моего первого пакета Node.js
Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

ИИ в аэрокосмической отрасли
Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


Для любых предложений по сайту: [email protected]