У меня возникают проблемы с получением правильного вывода из моего приложения OpenGL после перехода от обычного рисования с VBO / VAO к экземплярам массивов с VBO / VAO. Предполагается, что на выходе получится набор сфер, но вместо этого это сумасшедшие вершины, образующие странные треугольники. Я проверил позиции вершин в консоли отладчика, но там не было ничего подозрительного. Все они были в диапазоне от -10 до 10, и на сцене они, вероятно, достигли +/- 30.
Вот важные части моего кода. Пожалуйста, скажите мне, если я что-то не вижу. Буду весьма признателен за это!
char const *attribInSphereModelMatrix = "inSphereModelMatrix";
std::vector<glm::mat4> dNodesModelMatrices;
...
attributes[ATTRIB_SPHERE_MODEL_COLUMN0] = shader->getAttribLocation(attribInSphereModelMatrix);
attributes[ATTRIB_SPHERE_MODEL_COLUMN1] = attributes[ATTRIB_SPHERE_MODEL_COLUMN0] + 1;
attributes[ATTRIB_SPHERE_MODEL_COLUMN2] = attributes[ATTRIB_SPHERE_MODEL_COLUMN0] + 2;
attributes[ATTRIB_SPHERE_MODEL_COLUMN3] = attributes[ATTRIB_SPHERE_MODEL_COLUMN0] + 3;
...
// Create the vertex array object
glGenVertexArrays(1, &sphereVertexArray);
glBindVertexArray(sphereVertexArray);
// Create the buffer object to hold the sphere view matrix
glGenBuffers(1, &sphereModelMatrixBuffer);
glBindBuffer(GL_ARRAY_BUFFER, sphereModelMatrixBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::mat4) * dNodes.size(), &dNodesModelMatrices[0], GL_STATIC_DRAW);
// All matrix data is in one VBO, set the appropriate offsets
glEnableVertexAttribArray(attributes[ATTRIB_SPHERE_MODEL_COLUMN0]);
glVertexAttribPointer(attributes[ATTRIB_SPHERE_MODEL_COLUMN0], 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), NULL);
glVertexAttribDivisorARB(attributes[ATTRIB_SPHERE_MODEL_COLUMN0], 1);
glEnableVertexAttribArray(attributes[ATTRIB_SPHERE_MODEL_COLUMN1]);
glVertexAttribPointer(attributes[ATTRIB_SPHERE_MODEL_COLUMN1], 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (const GLvoid *)(sizeof(glm::vec4)));
glVertexAttribDivisorARB(attributes[ATTRIB_SPHERE_MODEL_COLUMN1], 1);
glEnableVertexAttribArray(attributes[ATTRIB_SPHERE_MODEL_COLUMN2]);
glVertexAttribPointer(attributes[ATTRIB_SPHERE_MODEL_COLUMN2], 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (const GLvoid *)(2 * sizeof(glm::vec4)));
glVertexAttribDivisorARB(attributes[ATTRIB_SPHERE_MODEL_COLUMN2], 1);
glEnableVertexAttribArray(attributes[ATTRIB_SPHERE_MODEL_COLUMN3]);
glVertexAttribPointer(attributes[ATTRIB_SPHERE_MODEL_COLUMN3], 4, GL_FLOAT, GL_FALSE, sizeof(glm::mat4), (const GLvoid *)(3 * sizeof(glm::vec4)));
glVertexAttribDivisorARB(attributes[ATTRIB_SPHERE_MODEL_COLUMN3], 1);
Как только я готов к настройке, я иду к чертежу.
glEnableVertexAttribArray(attributes[ATTRIB_SPHERE_MODEL_COLUMN0]);
glEnableVertexAttribArray(attributes[ATTRIB_SPHERE_MODEL_COLUMN1]);
glEnableVertexAttribArray(attributes[ATTRIB_SPHERE_MODEL_COLUMN2]);
glEnableVertexAttribArray(attributes[ATTRIB_SPHERE_MODEL_COLUMN3]);
...
glDrawElementsInstanced(GL_TRIANGLES, numSphereTris, GL_UNSIGNED_INT, NULL, (int)dNodes.size());
И вот важные части вершинного шейдера:
in mat4 inSphereModelMatrix;
...
void main()
{
vec4 v = vec4(inPosition, 1.0);
mat4 modelViewMatrix = viewMatrix * inSphereModelMatrix;
...
gl_Position = projectionMatrix * modelViewMatrix * v;
}
Результат выглядит так:
Пожалуйста, помогите мне как-нибудь. Я боролся с этим в течение последних 3 дней. Спасибо вам всем!
РЕДАКТИРОВАТЬ: Мне было интересно, было ли это как-то связано с основным порядком столбцов / строк, поэтому я попытался транспонировать матрицу, но пришел к выводу, что причина не в этом.
Я понял! Я попытался использовать объект текстуры буфера и gl_InstanceID
внутри шейдеров на самом деле получить столбцы матрицы, и это сработало! Я не могу поверить, что что-то, эквивалентное тому, что я сделал ранее, не должно работать, и использование объектов текстурного буфера (TBO) работает … Однако я собираюсь опубликовать важные части кода для будущих ссылок.
/// A texture buffer object to pass to the shaders
GLuint sphereModelMatrixTBO;
/// A texture holding the matrices data
GLuint sphereModelMatrixTex;
.
.
.
/// Vector containing the model matrices of the spheres
std::vector<glm::mat4> dNodesModelMatrices;
.
.
.
glGenBuffers(1, &sphereModelMatrixTBO);
glBindBuffer(GL_TEXTURE_BUFFER, sphereModelMatrixTBO);
glBufferData(GL_TEXTURE_BUFFER, sizeof(glm::mat4) * dNodes.size(), &dNodesModelMatrices[0], GL_STATIC_DRAW);
И в процедуре розыгрыша я делаю следующее:
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_BUFFER, sphereModelMatrixTex);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, sphereModelMatrixTBO);
glUniform1i(uniforms[UNIFORM_MODEL_MATRIX_BUFFER], 0);
.
.
.
glDrawElementsInstanced(GL_TRIANGLES, numSphereTris, GL_UNSIGNED_INT, NULL, (int)dNodes.size());
Вершинный шейдер теперь выглядит следующим образом:
uniform samplerBuffer sphereModelMatrixBuffer;
.
.
.
vec4 col1 = texelFetch(sphereModelMatrixBuffer, gl_InstanceID * 4);
vec4 col2 = texelFetch(sphereModelMatrixBuffer, gl_InstanceID * 4 + 1);
vec4 col3 = texelFetch(sphereModelMatrixBuffer, gl_InstanceID * 4 + 2);
vec4 col4 = texelFetch(sphereModelMatrixBuffer, gl_InstanceID * 4 + 3);
mat4 modelMatrix = mat4(col1, col2, col3, col4);
И это все, что вам нужно сделать, чтобы иметь полностью работающее быстрое приложение OpenGL! Вот как это выглядит сейчас:
Других решений пока нет …