【问题标题】:GLSL-based projection/model view makes object invisible基于 GLSL 的投影/模型视图使对象不可见
【发布时间】:2013-03-02 13:54:21
【问题描述】:

所以我正在尝试在 OpenGL 中迁移到更现代、基于着色器的渲染系统,据我了解,其中一部分是执行过去使用旧 OpenGL 中的内置矩阵堆栈完成的投影而是将我自己的矩阵提供给着色器。这是我的着色器(抱歉,由于某种原因,我无法让空格出现在代码格式中):

//Vertex

attribute vec3 coord3d;
attribute vec3 v_color;
varying vec3 f_color;
uniform mat4 projection;
uniform mat4 model;
uniform mat4 view;

void main(void) 
{
        gl_Position = projection * view * model * vec4(coord3d, 1.0);
        f_color = v_color;
}

//Fragment

varying vec3 f_color;

void main(void) 
{
    gl_FragColor = vec4(f_color.x, f_color.y, f_color.z, 1.0);
}

不过,我遇到了一些问题,因为投影和/或视图矩阵的乘法使我的测试对象消失了。如果我将着色器更改为:

gl_Position = model * vec4(coord3d, 1.0);

对象按预期显示在屏幕上,平坦且相对于屏幕的 [-1, 1] 空间定位。让我们一步一步来。

我有三个相关的类,我们称它们为 Scene、Object 和 Camera。在 Scene 的构造函数中,设置了这些 GLuint:

//Model - must be changed for each model
Object::ModelUniform = glGetUniformLocation(ObjectShader, "model");

//View - must be changed once per frame
m_ViewUniform = glGetUniformLocation(ObjectShader, "view");

//Projection - must only be set once    
m_ProjectionUniform = glGetUniformLocation(ObjectShader, "projection");
glm::mat4 projection = glm::perspective(60.0f, 1.33f, 0.1f, 512.f);
glUniformMatrix4fv(m_ProjectionUniform, 1, GL_FALSE, glm::value_ptr(projection));

然后,每帧一次(仍在场景中;我在后台有其他对象在旧着色器+glMultMatrixf() 代码上运行,但我认为两者之间没有任何交互):

glm::vec3 Eye = glm::vec3(CameraPos.x, CameraPos.y, CameraPosz);

glm::vec3 Center = glm::vec3(ObjectPos.x, ObjectPos.y, ObjectPosz);

glm::vec3 Up = glm::vec3(0.0, 1.0, 0.0);

glm::mat4 view = glm::lookAt(Eye, Center, Up);
glUniformMatrix4fv(m_ViewUniform, 1, GL_FALSE, glm::value_ptr(view));
glUseProgram(ObjectShader);
Object->Cycle();

然后,在 Object::Cycle() 中:

glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(Position.x, Position.y, Position.z));
glUniformMatrix4fv(Object::ModelUniform, 1, GL_FALSE, glm::value_ptr(model));
glEnableVertexAttribArray(CoordinateAttribute);
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
glVertexAttribPointer(CoordinateAttribute, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0);

glEnableVertexAttribArray(ColorAttribute);
glBindBuffer(GL_ARRAY_BUFFER, m_VertexBuffer);
glVertexAttribPointer(ColorAttribute, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*) (3 * sizeof(GLfloat)));

glDrawArrays(GL_TRIANGLES, 0, 6);

glDisableVertexAttribArray(ColorAttribute);
glDisableVertexAttribArray(CoordinateAttribute);

glDisable(GL_BLEND);

glBindBuffer(GL_ARRAY_BUFFER, 0);

所有我使用的矩阵都可以在旧 OpenGL 中使用已弃用的函数(如 glMultMatrixf())正常工作。

如上所述,仅使用模型矩阵可以正常工作。旋转相机不会找到丢失的对象。

这可能是什么问题?

【问题讨论】:

  • 你应该看看这个:stackoverflow.com/questions/4202456/…(它澄清了你什么时候可以和不可以直接在你的 glsl 着色器代码中使用内置的 gl_ModelViewProjectionMatrix 等)
  • 嗯,我的目标是 OpenGL 3.3+,所以 GLSL 3.3+ 也是如此。我没有使用已弃用的 gl_ModelViewProjectionMatrix,但我假设您指的是 gl_Position,它也已弃用?我是否应该简单地使用out vec4?这似乎也不起作用。
  • glEnableClientState 已弃用。
  • 天哪,这真是一个 TLDR; SSCCE 呢?

标签: c++ opengl 3d glsl shader


【解决方案1】:

这里:

glUniformMatrix4fv(m_ProjectionUniform, 1, GL_FALSE, glm::value_ptr(projection));

这里

glm::mat4 view = glm::lookAt(Eye, Center, Up);
glUniformMatrix4fv(m_ViewUniform, 1, GL_FALSE, glm::value_ptr(view));
glUseProgram(ObjectShader);
Object->Cycle();

您正在设置视图,但您在 之后激活了着色器。也许您对投影矩阵有同样的问题,但我无法从您的代码中看出。着色器需要处于活动状态才能在其上设置制服。在设置这些时,您可能只是没有着色器绑定。另一方面,仅从您发布的位来看,着色器可能始终处于活动状态,因此这将在第一帧之后起作用。这是不可能的。

【讨论】:

  • 就是这样!!谢谢!我从来不知道!我以为你可以随意设置制服。
  • 不客气。不幸的是,您对原始问题进行了如此多的编辑,这变成了一个社区 wiki,我没有得到任何想象的互联网点 ;-) 无论哪种方式,glUniform* 调用都不将程序作为参数(与 glGetUniformLocation 调用相反)作为它需要绑定程序的提示。是的,这是 OpenGL 的一个非常糟糕的方面..
【解决方案2】:

试试这个:

uniform mat4 ModelView;
uniform mat4 ProjectionView;

in vec4 position;

void main()
{
    gl_Position = ProjectionView * ModelView * position ;
}

矩阵乘法在 OpenGL 中从右到左进行。

【讨论】:

  • 不幸的是,这似乎没有帮助 - 屏幕上仍然没有任何可见的内容。
  • 那么,它肯定不是来自这里,可能是你的 VBO/Shader init 或 Rendering。
  • 好吧,我确实有一个旧的设置,可以与使用不推荐使用的函数的着色器一起正常工作 - 我已经添加了上面的代码。
  • 好吧,glEnableClientState 是您告诉 OpenGL 使用固定功能属性 (gl_Vertex, gl_Color) 的方式,但这些属性已从 Core Profile 中删除。您应该改用 glEnableVertexAttribArray 并指定您的位置数组或使用属性位置查看此link
  • 我已经更新了我的代码以反映 Wikibook 中的方法,并且一切正常,直到需要将投影、视图和模型矩阵相乘。如果我执行乘法,对象就会消失。仅乘以模型矩阵就可以正常工作,并且我可以毫无问题地旋转和平移事物(在屏幕空间中)。添加投影或视图矩阵会使对象消失。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-22
相关资源
最近更新 更多