0
votes

I'm trying to implement simplest possible diffuse lighting after reading a few tutorials, but fail miserably.

I load 3d mesh from Wavefront obj file and if I don't apply lighting, it looks just fine. But, when I do apply lighting, the animal looks like a chessboard and the cube is messed up even more:

animal comparison (with normals)

cube comparison (with normals)

Here is the vertex shader:

#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;
}

I pass fragment position and normals to the fragment shader as-is because I'm not applying any model transformations, I simply assume that a model already has world coordinates after loading it from file (forget about u_model uniform, it's not used for now).

Then, the fragment shader:

#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);
}

No model or normal matrices used, because no rotations (or scale) are applied to model for now.

I thought about incorrect normals, but at least a simple cube should have correct ones, right?

Also, maybe I should mention that I'm using NSOpenGLView under MacOS.

Any help will be appreciated. Thank you!

UPDATE:

Adding VBO setup.

This is how single vertex looks like:

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

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

I initialize my VAO like this

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 initialize method

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;
     }
 }

And buffer initialize method

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

Vertex will become Vertex1P1N1UV in this case

UPDATE:

Implemented normal visualization (reuploaded screenshots, scroll to top). What bothers me is that I can see normals through the mesh, like it's transparent despite opaque color. Is this a depth testing problem?

1
@Vallentin: Linear interpolation denormalizes normal vectors, so renormalizing them is not optional.Nicol Bolas
@NicolBolas Ohh right. Guess I shouldn't go on Stack Overflow first thing when I wake up.vallentin
@Vallentin updated the question, please tell me if I forgot some relevant informationPavlo Muratov
Could you update the questions with a display of your normals please ?Zouch
@Zouch working on normal visualization right now, will update as soon as I canPavlo Muratov

1 Answers

0
votes

After 2 days of struggling I found the problem. I did not enable depth buffer on NSOpenGLView. That is one line of code. If someone stumbles upon this, he can look here OpenGL GL_DEPTH_TEST not working for a solution.