У меня нет опыта ES, но я думаю, что многие вещи все еще применимы
Частично, это не заставляет вас использовать один VBO на тело, но у вас естьсделать один glDrawArrays
на тело.Они могут все еще получать свои данные из того же буфера, но это все еще не рекомендуется.Вместо этого я бы отошел от сложных примитивов, таких как веерные треугольники или полосы, и использовал бы индексированные списки треугольников, таким образом, все можно нарисовать за один вызов.Я сомневаюсь, что ES поддерживает расширение primitve_restart.При этом вы можете указать специальный индекс вершины, который перезапускает примитив.
Если вы получили много других статических атрибутов, было бы неплохо разделить позиции вершин в их собственном буфере (это, конечно, GL_DYNAMIC_DRAW
или даже GL_STREAM_DRAW
использование).Но если у вас есть только дополнительный 4-кубовый цвет или что-то подобное, дополнительные затраты на копирование могут быть не такими уж плохими, и вы можете получить большую прибыль от чередования, необходимо протестировать.
ЕслиВы обновляете их все каждый кадр, тогда полный glBufferData
может быть лучше, чем glBufferSubData
.Или вы можете также вызвать glBufferData(..., NULL)
, а затем glMapBuffer(..., GL_WRITE_ONLY)
, если вы не хотите хранить массив ЦП для ваших данных.Это говорит водителю, что вам больше не нужны предыдущие данные.Таким образом, драйвер может выделить для вас совершенно новый буфер, в то время как предыдущие данные все еще используются для рендеринга.Таким образом, вы можете выложить новые данные, когда старые все еще используются (старый буфер освобождается драйвером, когда он больше не используется).
заполнитель
Для цветов GL_UNSIGNED_BYTE
может быть даже лучше, так как они обычно не нуждаются в такой высокой точности.Это также может хорошо работать с оптимизацией выравнивания, когда, например, у вас есть 3 плавающие координаты и 4 байтовых цветовых канала, что дает вершину из 16 байтов, что очень удобно для выравнивания.В этом случае может быть целесообразно сохранить вершины и цвета в одном и том же буфере.
РЕДАКТИРОВАТЬ: Немного прояснить пункт 3: Если у вас есть данныев любом случае, в массиве ЦП вы можете просто вызвать glBufferData
со своими данными.Если вы хотите, чтобы драйвер выделил это хранилище для вас, вы можете использовать glMapBuffer
, который дает вам указатель на буферную память, отображаемую в адресное пространство ЦП (и, конечно, вы GL_WRITE_ONLY
, так как вы не заботитесь о предыдущемданные).Но в этом случае glBufferData
с нулевым указателем выделит совершенно новое хранилище для буфера (без копирования каких-либо данных), что говорит драйверу, что мы не заботимся о предыдущем содержимом (даже они могут в настоящее время *)1040 * все еще будет использоваться для рендеринга).Драйвер может оптимизировать этот случай и выделить новое хранилище под капотом, но все равно не освободить предыдущее хранилище, которое затем освобождается, когда предыдущие данные, наконец, больше не используются для рендеринга.Но имейте в виду, что you не создает другого буфера, он просто продолжается под капотом драйвера.Поэтому, когда вы хотите обновить весь буфер, вы можете либо сделать
updateData(dataArray);
glBufferData(GL_ARRAY_BUFFER, size, dataArray, usage);
, если вы все равно получили данные в свой собственный массив ЦП, либо
glBufferData(GL_ARRAY_BUFFER, size, NULL, usage);
dataArray = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
updateData(dataArray);
glUnmapBuffer(GL_ARRAY_BUFFER);
Если вы этого не сделаетенужна копия вашего процессора и вы хотите, чтобы драйвер позаботился.Но если обновлять данные поэтапно в течение всего приложения, то первое решение может быть лучше, поскольку вы не можете использовать буфер для рендеринга, пока он, конечно, отображается, и вы должны отображать буфер только на короткое время.