Я хотел бы реализовать инстансный рендеринг для моего механизма opengl, но я только что узнал, что максимальное количество входов, поддерживаемых вершинным шейдером, составляет всего 16 для моего GPU.
Это следующие матрицы, которые мне нужно переместить на вход:
uniform mat4 MVP;
uniform mat4 modelMatrix;
uniform mat3 normalMatrix;
uniform mat4 DepthBiasMVP;
Если я правильно понял, мне понадобится атрибут для каждого столбца каждой матрицы, поэтому мне понадобится пространство атрибутов 4 + 4 + 3 + 4 = 15. 19 с атрибутами, которые я уже использую (pos, color, texCoord, normal), и он вырастет до 20+, если я добавлю тангенсы и другие вещи.
Есть ли способ справиться с этим, или мне придется забыть инстинктивный рисунок? Скажем, мне удалось избавиться от одной из этих матриц (modelMatrix), и у меня около 15 - 16 атрибутов, будет ли она работать на разных графических процессорах? предел 16 является минимальным для всех GPU?
Обратите внимание, что 16 - минимальное количество атрибутов вершин, которое имеет ваша реализация; в большинстве случаев допускается, что вы можете запросить через:
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &n).
Теперь, пытаясь сохранить все ваши данные в массивах instanced, вы должны попытаться организовать то, что на самом деле является данными, которые вы хотите разделить на один экземпляр. У вас есть много объектов, которые отличаются друг от друга только местоположением и/или ориентацией? Тогда вам, вероятно, нужно только установить uniform modelMatrix
как массив instanced (который требует 4 вершинных атрибута, допустимое значение). Вам действительно нужна другая матрица зрения и проекции для каждого экземпляра? Возможно нет. То же самое относится к DepthBiasMVP
.
normalMatrix
требуется, если вы выполняете неравномерное масштабирование, и если вы планируете сделать это для каждого экземпляра, вам также необходимо установить normalMatrix
каждого экземпляра. Вы можете рассчитать их на CPU заранее и отправить их как атрибуты вершин, которые будут стоить вам еще 4 атрибута вершин. Другой вариант - вычислить normalMatrix
в вершинном шейдере, но это может немного замедлить шейдерный шейдер (возможно, приемлемый компромисс?).
Они должны уменьшить необходимую информацию для каждого экземпляра только для modelMatrix
и, возможно, для normalMatrix
, уже уменьшая ее наполовину. Может быть, у вас есть только одна позиция на один случай? В этом случае даже простой vec4
будет делать.
В основном, попробуйте подумать о том, какие данные вам действительно нужны для обновления на один экземпляр, и вы, скорее всего, будете удивлены, сколько данных вам действительно нужно для каждого экземпляра.
Можно хранить данные каждого экземпляра в однородных массивах, однородных объектах буфера или объектах текстурного буфера и использовать переменную gl_InstanceID
в GLSL для доступа к данным в объекте буфера. Равномерные массивы могут показаться самыми легкими, но наиболее ограниченными по размеру и, следовательно, применимы только для небольшого числа экземпляров. UBOs могут быть немного больше, но также весьма ограничены. С другой стороны, TBOs позволит вам много мегабайт данных, но вы должны соответствующим образом упаковать свои данные там. В вашем случае кажется, что вам нужны только типы float, поэтому достаточно базового формата с 32-битными поплавками.