代码之家  ›  专栏  ›  技术社区  ›  Community wiki

基于GLSL的投影/模型视图使对象不可见

  •  0
  • Community wiki  · 技术社区  · 3 年前

    因此,我试图在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的构造函数中,将设置以下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));
    

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

    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中运行良好,使用了glMultMatrix()等不推荐使用的函数。

    如上所述,仅使用模型矩阵可以很好地工作。旋转相机无法找到丢失的对象。

    这里可能有什么问题?

    2 回复  |  直到 13 年前
        1
  •  4
  •   ltjax    13 年前

    此处:

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

    您正在设置视图,但激活了着色器 之后 你这样做。也许你对投影矩阵也有同样的问题,但我无法从你的代码中判断出来。着色器需要处于活动状态才能在其上设置统一。您可能只是在设置这些着色器时没有绑定着色器。另一方面,仅从您发布的比特来看,着色器可能一直处于活动状态,因此这将在第一帧之后工作。不可能告诉他。

        2
  •  1
  •   dimmak111    13 年前

    试试这个:

    uniform mat4 ModelView;
    uniform mat4 ProjectionView;
    
    in vec4 position;
    
    void main()
    {
        gl_Position = ProjectionView * ModelView * position ;
    }
    

    在OpenGL中,矩阵相乘从右向左。

    推荐文章