【问题标题】:Setting up a MVP Matrix in OpenGL在 OpenGL 中设置 MVP 矩阵
【发布时间】:2014-03-03 07:50:37
【问题描述】:

我正在尝试学习 OpenGL 的基础知识,但在设置转换矩阵时遇到了问题。我制作了模型、视图和投影矩阵,但将它们发送到我的顶点着色器时遇到问题。

代码如下:

//Set up MVP
glm::mat4 model = glm::mat4();
GLint uniModel = glGetUniformLocation(program, "model");
glUniformMatrix4fv(uniModel, 1, GL_FALSE, glm::value_ptr(model));

glm::mat4 view = glm::lookAt(
    glm::vec3(2.5f, 2.5f, 2.0f),
    glm::vec3(0.0f, 0.0f, 0.0f),
    glm::vec3(0.0f, 0.0f, 1.0f));
GLint uniView = glGetUniformLocation(program, "view");
glUniformMatrix4fv(uniView, 1, GL_FALSE, glm::value_ptr(view));

glm::mat4 proj = glm::perspective(45.0f, 800.0f / 600.0f, 1.0f, 10.0f);
GLint uniProj = glGetUniformLocation(program, "proj");
glUniformMatrix4fv(uniProj, 1, GL_FALSE, glm::value_ptr(proj));

和着色器:

layout (location = 0) in vec3 position;

uniform mat4 model;
uniform mat4 view;
uniform mat4 proj;

void main() {
    gl_Position = proj * view * model * vec4(position, 1.0);
}

我认为我在设置制服时做错了,因为它不会绘制任何东西,即使我将模型、视图和项目设置为身份。可能是我打错了什么,但我真的找不到问题。

编辑:解决了,问题是我忘了先用glUseProgram()

【问题讨论】:

  • 首先要做的是检查所有可能的返回码,验证您的着色器程序是否已正确编译和链接,并确保您的制服有效。这应该很快缩小问题所在;在那之后,所有的赌注都被取消了。在这些情况下,使用glGetError() 进行二分搜索也非常有用。
  • @gavinb :我如何确保我的制服是有效的?我很确定这是问题所在,因为着色器编译并链接,我没有得到任何错误或其他东西。如果我这样做:gl_Position = vec4(position, 1.0) 在着色器中一切正常。我认为着色器认为所有矩阵都是 0 并将所有内容投影到 0。
  • 制服必须 >= 0 才有效。确保检查glGetProgram(GL_LINK_STATUS,...)。也别忘了glUseProgram()
  • @gavinb :谢谢,这是glUseProgram() 的事情。
  • 您应该尽可能预先计算proj * view * model,然后将其作为mvp 发送到Shader,而不是分别所有3 个然后在Shader 中计算。

标签: c++ opengl glsl


【解决方案1】:

首先要做的是检查所有可能的返回码,验证你的着色器程序是否正确编译和链接,并确保你的制服是有效的,这意味着位置值是>= 0

在您不知道哪里出错的情况下,使用 glGetError() 进行二分搜索也非常有用。

编译着色器后,确保选中glGetProgram(GL_LINK_STATUS,...)。最后,您必须调用glUseProgram() 来激活着色器。

正如@Vallentin 建议的那样,传入预先计算的 MVP 矩阵会更有效,因为它不会在应用程序和着色器之间发生变化。这在一定程度上简化了您的代码,类似于您的应用程序代码:

// Set up MVP matrices

glm::mat4 model = glm::mat4();

glm::mat4 view = glm::lookAt(
    glm::vec3(2.5f, 2.5f, 2.0f),
    glm::vec3(0.0f, 0.0f, 0.0f),
    glm::vec3(0.0f, 0.0f, 1.0f));

glm::mat4 proj = glm::perspective(45.0f, 800.0f / 600.0f, 1.0f, 10.0f);

glm::mat4 mvp = proj * view * model;

glUseProgram(prog);

GLint uniMvp = glGetUniformLocation(program, "mvp");
glUniformMatrix4fv(uniMvp, 1, GL_FALSE, glm::value_ptr(mvp));

然后是 GLSL:

// Shader code

layout (location = 0) in vec3 position;
uniform mat4 mvp;

void main() {
    gl_Position = mvp * vec4(position, 1.0);
}

此外,您可以缓存统一位置,因为它们一旦编译就不会改变。这将在每帧中节省少量,而不是在每次重绘时查询它们。

【讨论】:

  • 如果我错了,请原谅我,但不是 'glm::mat4 mvp = model * view * proj;'应该是'glm::mat4 mvp = proj * view * model;' ?
  • 嗯...可能,是的。我已经更新了答案以与原始答案保持一致。尽管有一些微妙之处 - 列优先矩阵等价于以相反顺序相乘的行优先矩阵。 computergraphics.stackexchange.com/questions/5374/… 只是为了让我们保持警惕!
  • 每次glUseProgram之后是否需要再次调用glGetUniformLocation?还是位置保持不变?
  • 可以肯定,一旦着色器编译完成,位置就固定了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多