Чтобы использовать объект массива вершин в OpenGL 3.0, мы используем следующие шаги для создания имени объекта массива вершин и затем связываем его с контекстом.

  • glGenVertexArrays (1, & VAO) = генерирует имя массива вершин
  • glBindVertexArrays (& VAO) = связывает имя с массивом вершин.

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

  • glGenBuffers (1, & VBO) = сгенерировать имя для буфера вершин
  • glBindBuffer (GL_ARRAY_BUFFER, VBO) = привязать имя к GL_ARRAY_BUFFER
  • glBufferData (....) = Выделить память и заполнить данные

Поскольку в этих строках мы не выделили память для Vertex Array Object , означает ли это, что память для Vertex Array Object уже выделена как часть Context < / strong> и с помощью glBindVertexArrays () мы ссылаемся на указатель на выделенную память для объекта массива вершин?

1
user2259784 28 Июн 2017 в 23:45

1 ответ

Лучший ответ

glBufferData (....) = Выделить память и заполнить данные

Вы действительно выделяете память для буфера. Но это отличается от выделения памяти для объекта буфера.

Давайте выразим это в терминах C ++. Буферный объект похож на vector<char>. Выполнение glGenBuffers/glBindBuffer похоже на выделение объекта vector<char> (и давайте сделаем это в куче):

auto buffer = new vector<char>;

buffer указывает на реальный живой объект. sizeof(*buffer) вернет количество байтов памяти, которое требуется для объекта, на который указывает buffer. Вы можете запросить buffer->size(), и он вернет допустимое и четко определенное значение.

glGetBufferParameteri64v(target, GL_BUFFER_SIZE) будет эквивалентом вызова buffer->size(). Вы можете вызвать эту функцию после создания объекта, прежде чем вызывать glBufferData.

В обоих случаях, buffer->size() и GL_BUFFER_SIZE, возвращается размер 0. Поскольку вы еще ничего не поместили в объект. В обоих случаях объект теперь существует, но он пуст .

glBufferData - это как позвонить buffer->resize. Теперь вы сообщаете объекту, который вы выделили для самого , выделить некоторое хранилище определенного размера и (необязательно) заполнить его определенными данными.

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

VAO в нашей аналогии с C ++ больше похож на обычную структуру:

struct VAO
{
  int elementBuffer;
  VertexFormat vf[16];
  VertexBufferBinding vb[16];
};

Эта структура VAO не требует выделенного хранилища сверх sizeof(VAO). Как и многим объектам C ++, не нужно выделять память, кроме самих себя. Следовательно, у него нет эквивалента glBufferData.

Итак, чтобы ответить на ваш вопрос, память для всех объектов OpenGL принадлежит контексту OpenGL, который их создал. Просто некоторые объекты OpenGL могут иметь дополнительное хранилище помимо их основного объекта. vector<char> имеет внутренний массив байтов. И буферные объекты имеют внутренний массив байтов.

VAO не имеют внутренних массивов хранения за пределами самого объекта.

4
Nicol Bolas 29 Июн 2017 в 00:22
Николь, спасибо за объяснение! Верно ли, что буфер вершин находится в памяти графического процессора (VRAM) и в объекте массива вершин на стороне клиента / памяти процессора (RAM)? Если это так, как объект массива вершин, который живет в ОЗУ, может указывать на данные во VRAM?
 – 
user2259784
30 Июн 2017 в 03:21
1
@ user2259784: Где хранятся фактические данные для любого объекта, это деталь реализации. Выделенное хранилище для буферного объекта находится в доступной графическому процессору памяти. Означает ли это «VRAM» или нет, зависит от драйвера.
 – 
Nicol Bolas
30 Июн 2017 в 03:31