我正在尝试使用GLM渲染一个对象进行矩阵变换,但我得到了这个:
编辑:忘记提及我试图呈现的对象是一个简单的圆环。
我做了很多挖掘,我发现有一件事是glGetUniformLocation(program, "mvp")
返回-1
。如果统一变量未在着色器中使用,即使声明了变量,文档也会返回-1
。如下所示,它已被声明并正在顶点着色器中使用。我已经对program
进行了检查,以确保其有效,等等。
所以我的问题是:
为什么glGetUniformLocation(program, "mvp")
返回-1
,即使它已被声明并且正在顶点着色器中使用?
另一件我不太清楚的事情。我的GameObject类有一个名为Mesh的结构,包含变量GLuint vao
和GLuint[4] vbo
(顶点数组对象)和(顶点缓冲区对象)。我正在使用Assimp,我的GameObject类基于this tutorial。使用以下命令以与教程相同的方式呈现网格:
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, elementCount, GL_UNSIGNED_INT, NULL);
我不确定VAO和VBO是如何工作的。我发现如果您希望在整个程序中访问顶点阵列,则使用VAO,如果您只是想将其发送到显卡而不是触摸,则使用VBO它再次(纠正我,如果我在这里错了)。那么为什么教程会混合它们呢?在网格的构造函数中,它创建并绑定VAO,然后不为构造函数的其余部分触摸它(除非创建和绑定VBO对当前绑定的VAO有影响)。然后继续为顶点缓冲区,普通缓冲区,纹理坐标缓冲区和索引缓冲区创建和绑定VBO。要渲染对象,它会绑定VAO并调用glDrawElements
。我感到困惑的是OpenGL如何/在何处访问VBO,如果它不能用于教程中的设置,我很确定它可以,需要什么改变?
void GameObject::render() {
GLuint program = material->shader->program;
glUseProgram(program);
glm::mat4 mvp = Game::camera->mvpMatrix(this->position);
GLuint mvpLoc = glGetUniformLocation(program, "mvp");
printf("MVP Location: %d\n", mvpLoc); // prints -1
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, &mvp[0][0]);
for (unsigned int i = 0; i < meshes.size(); i++) {
meshes.at(i)->render(); // renders element array for each mesh in the GameObject
}
}
顶点着色器(简单的未点亮红色):
#version 330 core
layout(location = 0) in vec3 position;
uniform mat4 mvp;
out vec3 vertColor;
void main(void) {
gl_Position = mvp * vec4(position, 1);
vertColor = vec3(1, 0, 0);
}
片段着色器:
#version 330 core
in vec3 vertColor;
out vec3 color;
void main(void) {
color = vertColor;
}
答案 0 :(得分:1)
问题1
你自己几乎已经回答了这个问题。 glGetUniformLocation(program, name)
获取着色程序"mvp"
中统一program
的位置,如果未宣布制服(或未使用,则返回-1):如果您不使用它,它没有被编译)。您的着色器确实声明并使用mvp,这强烈表明编译程序存在问题。你确定你在程序中使用这个着色器吗?
问题2
VBO存储GPU将使用的数据值。这些可以是颜色值,法线,纹理坐标,无论你喜欢什么。 VAO用于表达您的VBO的布局 - 将其视为地图,向您的程序指示在哪里可以找到VBO中的数据。
示例程序在调用glVertexAttribPointer时会触摸VAO,例如
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
这与你失踪的制服无关。