Количество атрибутов для каждой вершины, которое мне нужно для расчета выходных данных моего вершинного шейдера, больше, чем GL_MAX_VERTEX_ATTRIBS. Есть ли эффективный способ, например, указать количество буферов, использующих единый массив индексов, и таким образом получить доступ к данным на каждую вершину?
Это аппаратное ограничение, поэтому короткий ответ — нет.
Если вы рассматриваете обходные пути для других способов, таких как использование униформ, которые также имеют ограничения, так что это тоже не вариант.
Один из возможных способов, который я могу назвать довольно хакерским, — это получить дополнительные данные из текстуры. Так как вы можете получить доступ к текстурам из вершинного шейдера, но фильтрация текстур не поддерживается (вам это не нужно, так что для вас это не имеет значения).
С новыми OpenGL стало возможным хранить довольно большой объем данных в текстурах и получать к ним доступ без ограничений даже в вершинном шейдере. Похоже, это один из способов.
Хотя при таком подходе есть проблема, с которой вам нужно столкнуться, откуда вы знаете текущий индекс, то есть какая это вершина?
Вы можете проверить встроенный gl_VertexID для этого.
Вы можете обойти входной ассемблер и связать дополнительные атрибуты в SSBO или текстуре. Затем вы можете использовать gl_VertexID в вершинном шейдере, чтобы получить значение записи в индексном буфере, которую вы в данный момент визуализируете (например: индекс в данных вершины, из которых вы должны прочитать)
Так, например, в VS следующий код по существу идентичен (однако он может иметь разные характеристики производительности в зависимости от вашего оборудования)
in vec3 myAttr;
void main() {
vec3 vertexValue = myAttr;
//etc
}
против
buffer myAttrBuffer {
vec3 myAttr[];
};
void main() {
vec3 vertexValue = myAttr[gl_VertexID];
//etc
}
Код привязки на стороне процессора отличается, но в целом это концепция. myAttr учитывается в GL_MAX_VERTEX_ATTRIBS, но myAttrBuffer этого не делает, поскольку он загружается шейдером явно.
Вы даже можете использовать один и тот же буферный объект в обоих случаях, связавшись с другой целью.
Если вы не можете полностью ограничить себя атрибутами GL_MAX_VERTEX_ATTRIBS, я бы посоветовал использовать многопроходные шейдеры. Перепроектируйте ваш код для работы с данными с половиной набора атрибутов в первом проходе, а оставшихся — во втором проходе.