2

I am having troubles getting the correct output from my OpenGL application after switching from normal drawing with VBOs/VAOs to instanced arrays with VBOs/VAOs. The output is supposed to be a bunch of spheres, but instead it's crazy positioned vertices forming strange triangles. I've checked the vertex positions in the debugger console, but there didn't seem to be anything suspicious. They were all in the range from -10 to 10 and in the scene they are going to probably +/-30.

Here are the important parts of my code. Please tell me if I am not seeing something. I would greatly appreciate it!

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);

Once I'm ready with the setup I go to the drawing.

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());

And here are the important parts of the vertex shader:

in mat4 inSphereModelMatrix;

...

void main()
{
    vec4 v = vec4(inPosition, 1.0);
    mat4 modelViewMatrix = viewMatrix * inSphereModelMatrix;

    ...

    gl_Position = projectionMatrix * modelViewMatrix * v;
}

The result looks like this:

end result

Please help me somehow. I've been struggling with this for the past 3 days. Thank you all!

EDIT: I have been wondering if it had something to do with the column/row major order, so I've tried transposing the matrix, but I came to the conclusion that was not what's causing the issue.

4

1 回答 1

2

我懂了!我已经尝试使用纹理缓冲区对象和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 应用程序所需要做的一切!这是它现在的样子:

于 2013-11-02T10:43:30.097 回答