漫射照明工件(OpenGL 4)

时间:2017-04-09 10:37:55

标签: macos opengl 3d glsl lighting

我在阅读一些教程后尝试实现最简单的漫反射光照,但却失败了。

我从Wavefront obj文件加载3d网格,如果我不应用光照,它看起来很好。但是,当我使用照明时,动物看起来像棋盘,立方体更加混乱:

animal comparison (with normals)

cube comparison (with normals)

这是顶点着色器:

#version 400

layout (location = 0) in vec4 a_position;
layout (location = 1) in vec3 a_texCoords;
layout (location = 2) in vec3 a_normal;

uniform mat4 u_viewProjection;
uniform mat4 u_model;

out vec3 v_fragPos;
out vec3 v_fragNormal;

void main() {
    v_fragPos = a_position.xyz;
    v_fragNormal = a_normal;
    gl_Position = u_viewProjection * a_position;
}

我将片段位置和法线按原样传递给片段着色器,因为我没有应用任何模型变换,我只是假设模型在从文件加载后已经具有世界坐标(忘记u_model制服,它&& #39;现在不用了。)

然后,片段着色器:

#version 400

uniform vec3 u_lightPos;
uniform vec3 u_lightColor;

uniform vec3 u_diffuseColor;
uniform vec3 u_specularColor;
uniform vec3 u_ambientColor;

in vec3 v_fragPos;
in vec3 v_fragNormal;

out vec4 o_fragColor;

void main() {
    vec3 lightDir = u_lightPos - v_fragPos;    
    float cosTheta = max(dot(normalize(v_fragNormal), normalize(lightDir)), 0.0);
    vec3 diffuseContribution = cosTheta * u_lightColor;

    o_fragColor = vec4(u_diffuseColor * diffuseContribution, 1.0);
}

没有使用模型或普通矩阵,因为现在没有对模型应用旋转(或缩放)。

我想到了不正常的法线,但至少一个简单的立方体应该有正确的,对吧?

另外,也许我应该提一下,我在MacOS下使用NSOpenGLView。

任何帮助将不胜感激。 谢谢!

更新

添加VBO设置。

这是单个顶点的样子:

struct Vertex1P1N1UV {
        glm::vec4 mPosition;
        glm::vec3 mTextureCoords;
        glm::vec3 mNormal;

        Vertex1P1N1UV();
        Vertex1P1N1UV(glm::vec4 position, glm::vec3 texcoords, glm::vec3 normal);
};

我像这样初始化我的VAO

auto* VAO = new GLVertexArray<Vertex1P1N1UV>();
VAO->initialize(subMesh.vertices(), GLVertexArrayLayoutDescription({
                static_cast<int>(glm::vec4::length() * sizeof(GLfloat)),
                static_cast<int>(glm::vec3::length() * sizeof(GLfloat)),
                static_cast<int>(glm::vec3::length() * sizeof(GLfloat)) }));

VAO初始化方法

void initialize(const std::vector<Vertex>& vertices, const GLVertexArrayLayoutDescription& layoutDescription) {
    bind();

    mVertexBuffer.initialize(vertices);

    GLuint offset = 0;
    for (GLuint location = 0; location < layoutDescription.getAttributeSizes().size(); location++) {
         glEnableVertexAttribArray(location);
         GLsizei attributeSize = layoutDescription.getAttributeSizes()[location];
         glVertexAttribPointer(location, attributeSize / sizeof(GLfloat), GL_FLOAT, GL_FALSE, sizeof(Vertex), reinterpret_cast<void *>(offset));
         offset += attributeSize;
     }
 }

缓冲区初始化方法

void initialize(const std::vector<Vertex>& data) override {
     bind();
     glBufferData(GL_ARRAY_BUFFER, data.size() * sizeof(Vertex), data.data(), GL_STATIC_DRAW);
}

在这种情况下,顶点将变为Vertex1P1N1UV

更新

实现了正常的可视化(重新上传的屏幕截图,滚动到顶部)。 困扰我的是我可以通过网格看到法线,尽管它是透明的,尽管颜色不透明。这是深度测试问题吗?

1 个答案:

答案 0 :(得分:0)

经过2天的挣扎,我发现了这个问题。 我没有在NSOpenGLView上启用深度缓冲。这是一行代码。 如果有人偶然发现这一点,他可以看看OpenGL GL_DEPTH_TEST not working 寻求解决方案。