Я использую openglEs 2.0. Я работаю над аппаратным скином. Я пытаюсь передать индексы костей как ivec4, однако компилятор говорит мне, что невозможно использовать ivec4 в качестве атрибута вершины. Как я могу преодолеть эту стуацию?
Вот мой код вершинного шейдера.
0(1) : error C7507: OpenGL does not allow attributes of type ivec4
"struct Bone""{"" mat4 transform;"" mat4 bindPose;""};""attribute vec3 vPosition;""attribute vec3 vNormal;""attribute vec2 vTexture;""attribute ivec4 vBones;""attribute vec4 vWeights;""uniform mat4 projectViewModel;""uniform Bone bones[64];""varying vec3 v_normal;""varying vec2 v_texCoord;""void main()""{"" gl_Position = bones[vBones.x].transform * bones[vBones.x].bindPose * vec4(vPosition, 1.0) * vWeights.x;"" gl_Position += bones[vBones.y].transform * bones[vBones.y].bindPose * vec4(vPosition, 1.0) * vWeights.y;"" gl_Position += bones[vBones.z].transform * bones[vBones.z].bindPose * vec4(vPosition, 1.0) * vWeights.z;"" gl_Position += bones[vBones.w].transform * bones[vBones.w].bindPose * vec4(vPosition, 1.0) * vWeights.w;"" gl_Position = projectViewModel * gl_Position;"" v_texCoord = vTexture;"" v_normal = vNormal;""}";
ОБНОВИТЬ:
Как мне сказали, я изменил код шейдера и код на стороне клиента. Вот код на стороне клиента:
glEnableVertexAttribArray(3); // Bones
glVertexAttribPointer(3, 4, GL_INT, GL_FALSE, object->m_mesh->GetVertexSize(), (const void*)offset);
И вот как я получаю доступ к индексам костей в коде шейдера:
gl_Position = bones[int(vBones.x)].transform * bones[int(vBones.x)].bindPose * vec4(vPosition, 1.0) * vWeights.x;
Если я запускаю этот код на Windows PC. Это работает просто отлично, однако, когда я скомпилировал его с emscripten для веб-браузеров. Выдает ошибку gl 1282 (недопустимая операция).
Если я изменю на GL_FLOAT, это исправит ошибку gl, однако, все индексы костей станут равны 0, и я получу сетку без кожи, потому что кость 0 имеет единичные матрицы как связующую и всемирную матрицу.
Целочисленные атрибуты не поддерживаются в ES 2.0. Из спецификации GLSL ES 1.00 (которая является версией GLSL, используемой с ES 2.0):
Спецификатор атрибута может использоваться только с типами данных float, vec2, vec3, vec4, mat2, mat3 и mat4.
Самое близкое, что вы можете сделать, это использовать vec4
в коде шейдера и приведите значения с плавающей точкой к целым числам, где это необходимо.
Если ваши данные на стороне клиента находятся в целочисленном формате, вы должны быть осторожны с glVertexAttribPointer()
вызов. Логическое значение, переданное в качестве 4-го аргумента, указывает, хотите ли вы, чтобы значения были нормализованы или их нужно было преобразовать в плавающее без нормализации. В вашем случае вы захотите пройти GL_FALSE
, Например, если у вас есть байтовые данные в вашем клиентском коде:
glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
ES 3.0 и выше поддерживают целочисленные атрибуты. Так что вы можете использовать ivec4
для атрибута и укажите значения с glVertexAttribIPointer()
(обратите внимание на дополнительные I
в имени функции) в коде вашего клиента.
Других решений пока нет …