Переназначить значение буфера шейдера - PullRequest
0 голосов
/ 28 августа 2018

В на этот вопрос о растущих буферах кто-то отвечает следующим кодом.

// Bind the old buffer to `GL_COPY_READ_BUFFER`
glBindBuffer (GL_COPY_READ_BUFFER, old_buffer);

// Allocate data for a new buffer
glGenBuffers (1, &new_buffer);
glBindBuffer (GL_COPY_WRITE_BUFFER, new_buffer);
glBufferData (GL_COPY_WRITE_BUFFER, ...);

// Copy `old_buffer_size`-bytes of data from `GL_COPY_READ_BUFFER`
//   to `GL_COPY_WRITE_BUFFER` beginning at 0.
glCopyBufferSubData (GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, old_buffer_size);

Это мое понимание вышесказанного, чтобы скопировать А в Б:

Bind A
Generate B
Bind B
Write null contents to B at larger size
Copy A to B

Моя проблема в том, что A является исходным буфером вершин для шейдера, но так же, как и B (так как изменение размера является целью). В моем коде (C # opentk) шейдер сообщает мне идентификатор буфера, который совпадает с именованной переменной шейдера, используя GL.GetActiveAttrib, я не могу найти, как заставить его использовать буфер, отличный от того, который он дает.

Так что мне нужно либо переназначить шейдер, чтобы потом использовать B, либо сделать двойную копию:

Bind A
Generate B
Bind B
Write null contents to B at larger size
Copy A to B
Reassign shader to use B
Write null contents to A at larger size (size of B)
Copy B to A

Можно ли заставить его использовать определенный буфер или избежать двойного копирования?

1 Ответ

0 голосов
/ 28 августа 2018

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

Хорошей новостью является то, что вы можете повторно связать буфер с другой целью. Это то, что вы можете сделать в вашем буфере-менеджере (кажется, вы ошибочно называете это «шейдер». Шейдер - это программа в GPU). Не требуется второй экземпляр.

GL_COPY_READ_BUFFER и GL_COPY_WRITE_BUFFER цели полезны, если вы хотите сохранить предыдущие привязки. Это не ваш случай, поэтому копия проще:

//The buffer must be bound before copying it
glBindBuffer(GL_ARRAY_BUFFER, oldBuf); //or GL_ELEMENT_ARRAY_BUFFER or whatever it was
//New buffer
glGenBuffers (1, &newBuf);
//GL_COPY_WRITE_BUFFER is needed because GL_ARRAY_BUFFER is in use by oldBuf
glBindBuffer (GL_COPY_WRITE_BUFFER, newBuf);
glBufferData (GL_COPY_WRITE_BUFFER, newSize, ...);
glCopyBufferSubData (GL_ARRAY_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, old_buffer_size);

Теперь копирование завершено, буфер oldBuf можно безопасно удалить.

Осталось сделать две вещи:

a) Tell the buffer-manager to use 'newBuf' insted of 'oldBuf'
b) Before using this new buffer, re-bind it to the target you need
   glBindBuffer(GL_ARRAY_BUFFER, newBuf);

Ну, есть еще одна вещь, которую нужно сделать. Когда VAO был связан и ассоциация «атрибут - буфер для чтения» была установлена ​​glVertexAttribPointer, он использовал буфер oldBuf. Но теперь вы хотите еще один буфер. Поэтому вы должны снова связать этот VAO, связать новый буфер и использовать glVertexAttribPointer.


Лучшим решением может быть наличие большого буфера и использование только его части. Допустим, у вас есть VBO на миллион вершин. 1M x 3 с плавающей запятой x 4 байта = 12M байтов. Это не тот размер, с которым не может справиться не слишком старый графический процессор.

Если ваши данные изменяются в размере, но не превышают 1М вершин, то самый простой способ - использовать glBufferSubData и загружать новые данные, даже если это просто добавленные данные. Нет нового буфера, нет копии, нет изменения состояния VAO.

...