Вариант 1. Создайте разные VAO для каждого шейдера
VAO определяет сопоставление ваших атрибутов шейдера (например, считывает vec3 из этого места памяти в VBO, с шагом N байтов, и сопоставьте его с атрибутом, связанным с местоположением X).
Некоторые глобальные для хранения имени VAO
GLuint g_vao;
Затем для его создания (для макета данных, который вы определили в своем шейдере) :
// create the VAO
glCreateVertexArrays(1, &g_vao);
// set up: layout(location = 0) in vec3 aPos;
glEnableVertexArrayAttrib(g_vao, 0); //< turn on attribute bound to location 0
// tell OpenGL that attribute 0 should be read from buffer 0
glVertexArrayAttribBinding(
g_vao, //< the VAO
0, //< the attribute index (location = 0)
0); //< the vertex buffer slot (start from zero usually)
// tell openGL where within the buffer the data exists
glVertexArrayAttribFormat(
g_vao, //< the VAO
0, //< the attribute index
3, //< there are 3 values xyz
GL_FLOAT, //< all of type float
GL_FALSE, //< do not normalise the vectors
0); //< the offset (in bytes) from the start of the buffer where the data starts
// set up: layout(location = 1) in vec4 aBoneWeights
glEnableVertexArrayAttrib(g_vao, 1); //< turn on attribute bound to location 0
// tell OpenGL that attribute 1 should be read from buffer 0
glVertexArrayAttribBinding(
g_vao, //< the VAO
1, //< the attribute index (location = 1)
0); //< the vertex buffer slot (start from zero usually)
// tell openGL where within the buffer the data exists
glVertexArrayAttribFormat(
g_vao, //< the VAO
1, //< the attribute index
4, //< there are 4 values
GL_FLOAT, //< all of type float
GL_FALSE, //< do not normalise the vectors
sizeof(float) * 8); //< the offset (in bytes) from the start of the buffer where the data starts
// set up: layout(location = 2) in vec4 aBoneIndices;
glEnableVertexArrayAttrib(g_vao, 2); //< turn on attribute bound to location 2
// tell OpenGL that attribute 2 should be read from buffer 0
glVertexArrayAttribBinding(
g_vao, //< the VAO
2, //< the attribute index (location = 2)
0); //< the vertex buffer slot (start from zero usually)
// tell openGL where within the buffer the data exists
glVertexArrayAttribFormat(
g_vao, //< the VAO
2, //< the attribute index
4, //< there are 4 values xyz
GL_FLOAT, //< all of type float
GL_FALSE, //< do not normalise the vectors
sizeof(float) * 12); //< the offset (in bytes) from the start of the buffer where the data starts
Однако, я думаю, что ваше определение шейдера неверно для атрибута 2 (потому что вам придется передавать индексы костей в виде данных с плавающей запятой, что мне кажется очень неправильным!) .
Я бы подумал, что вам нужны целые числа вместо чисел:
layout(location = 2) in ivec4 aBoneIndices;
Однако при связывании с целыми числами вам нужно использовать glVertexArrayAttribIFormat вместо glVertexArrayAttribFormat:
glVertexArrayAttribIFormat(
g_vao, //< the VAO
2, //< the attribute index
4, //< there are 4 indices
GL_UNSIGNED_INT, //< all of type uint32
sizeof(float) * 12);
После всего этого вам необходимо привязать буфер вершин к нулевому слоту вершины, который вы использовали выше ...
glVertexArrayVertexBuffer(
g_vao, //< the VAO
0, //< the vertex buffer slot
0, //< offset (in bytes) into the buffer
sizeof(float) * 16); //< num bytes between each element
Вариант 2: Просто используйте тот же VAO и тот же VBO
Просто закодируйте индексы, чтобы иметь определенные значения c, и тогда вы всегда сможете использовать один и тот же VAO.
layout(location = 0) in vec3 aPos;
//layout(location = 1) in vec4 aCol; //< not used in this shader
//layout(location = 2) in vec4 aUv; //< not used in this shader
layout(location = 3) in vec4 aBoneWeights;
layout(location = 4) in vec4 aBoneIndices;
/ edit В ответ на ваш вопрос, это очень сильно зависит от версии OpenGL, которую вы используете. Ответ, который я разместил здесь, использует последние расширения прямого доступа к состоянию (DSA), найденные в OpenGL4.5. Если вы можете использовать их, я настоятельно рекомендую это сделать.
OpenGL 3.0: glVertexAttribPointer
Да, это будет работать. Однако этот механизм тесно связан с парадигмой OpenGL bind . Каждый атрибут эффективно связан с буфером, который был связан при вызове glVertexAttribPointer (т.е. вы будете делать: glBindBuffer (); glEnableVertexAttribArray (); glVertexAttribPointer ();) *) 1048 *.
Проблема с этим заключается в том, что он как бы блокирует вас для создания VAO для каждого VBO (или набора VBO, если извлекает данные из более чем одного) , поскольку атрибуты связаны с Точный буфер, который был связан, когда вы указали этот атрибут.
OpenGL 4.3: glVertexAttribFormat
Эта версия очень похожа на ту, что я представил выше. Вместо того, чтобы передавать VAO в вызов функции, вы сначала вызываете glBindVertexArray (если вы ищете документы по вышеуказанным методам, те, у которых нет аргумента VAO, просто используют текущий связанный VAO) .
Преимущество этого подхода по сравнению со старым API заключается в том, что привязать VAO к другому VBO (-ям) тривиально [то есть вы можете связать VAO с программой GLSL вместо того, чтобы иметь VAO для каждой пары VBO / Program] - просто вызов glBindVertexBuffer для каждого VBO, и он будет хорошо работать.
OpenGL 4.5: glVertexArrayAttribFormat
В долгосрочной перспективе это самая простая версия API для использования. Основным преимуществом является то, что вам не нужно беспокоиться о том, какой VAO в настоящее время связан (потому что вы передаете его в качестве аргумента) . Это имеет ряд преимуществ, потому что вам больше не важно, какой VAO был связан, и это также открывает двери для изменения объектов OpenGL из другого потока (чего не позволяли старые версии API).