0

I have this code but the light seems not working correctly, when I render the object it's dark, then when I rotate it, the light source seems to be rotated too. I can't figure out where the problem is. I tried to modify the model for the light but still not working

this is the program:

while (!glfwWindowShouldClose(window))
    {

        /* Render here */
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        glm::mat4 view = glm::mat4(1.0f); 
        glm::mat4 projection = glm::mat4(1.0f);
        projection = glm::perspective(glm::radians(45.0f), (float)width / (float)heigh, 0.1f, 100.0f);

        view = glm::translate(view, glm::vec3(0.0f, 0.0f, transZ)); //this is for scroll mouse
        view = glm::translate(view, glm::vec3(0.0f, 0.0f, -2.0f));
        view = glm::translate(view, glm::vec3(0.0f, 0.0f, -5.0f));
                
        glUseProgram(programT);
        int lightColorLoc = glGetUniformLocation(programT, "lightColor");
        glUniformMatrix4fv(lightColorLoc, 1, GL_FALSE, glm::value_ptr(glm::vec3(1.0f, 0.0f, 0.0f)));

        int objectColorLoc = glGetUniformLocation(programT, "objectColor");
        glUniformMatrix4fv(objectColorLoc, 1, GL_FALSE, glm::value_ptr(glm::vec3(1.0f, 0.5f, 0.31f)));

        glm::vec3 lightPos(2.0f, 4.0f, 5.0f);
        int lightPosLoc = glGetUniformLocation(programT, "lightPos");
        glUniformMatrix4fv(lightPosLoc, 1, GL_FALSE, glm::value_ptr(lightPos));

        int projectionLocLight = glGetUniformLocation(programT, "projection");
            glUniformMatrix4fv(projectionLocLight, 1, GL_FALSE, glm::value_ptr(projection));
        glm::mat4 modelLight = glm::mat4(1.0f);
        int modelLocLight = glGetUniformLocation(programT, "model");
        glUniformMatrix4fv(modelLocLight, 1, GL_FALSE, glm::value_ptr(modelLight));

        glm::mat4 viewLight = glm::mat4(1.0f); 
        int viewLocLight = glGetUniformLocation(programT, "view");
        glUniformMatrix4fv(viewLocLight, 1, GL_FALSE, glm::value_ptr(viewLight));

        int viewLoc = glGetUniformLocation(programT, "view");
        glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));

        int projectionLoc = glGetUniformLocation(programT, "projection");
        glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));

        model = glm::rotate(model, glm::radians(rotX), glm::vec3(1.0f, 0.0f, 0.0f));
        model = glm::rotate(model, glm::radians(rotY), glm::vec3(.0f, 1.0f, .0f));
        model = glm::rotate(model, glm::radians(rotZ), glm::vec3(.0f, 0.0f, 1.0f));
        int modelLoc = glGetUniformLocation(programT, "model");
        glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));

                 

        glGenerateMipmap(GL_TEXTURE_2D);
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, textureArray[0]);
        glUniform1i(glGetUniformLocation(programT, "ourTexture"), 0);
            


            glBindVertexArray(VAOArray[0]);
        glDrawArrays(GL_TRIANGLES, 0, myMeshes.at(0).Indices.size());
    

        
        /* Swap front and back buffers */
        glfwSwapBuffers(window);

        /* Poll for and process events */
        glfwPollEvents();
        glfwSetKeyCallback(window, key_callback);
        glfwSetScrollCallback(window, scroll_callback);
        glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
        
    }

the following is my vertex shader:

#version 330 core


layout (location = 0) in vec3 RealPos;
layout (location = 1) in vec3 vertex_color;
layout (location = 2) in vec2 vertex_textcoord;
layout (location = 3) in vec3 RealNor;


out vec3 vs_pos;
out vec3 vs_color;
out vec2 vs_text;
out vec3 normal;
out vec3 FragPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;


void main()
{
    vs_pos = RealPos;
    vs_color = vertex_color;
    vs_text=vertex_textcoord;
    
    normal=RealNor;
    FragPos = vec3(model * vec4(vs_pos, 1.0));
    
    gl_Position = projection * view * model * vec4(vs_pos, 1.0);
}

and the following is the fragment shader:

#version 330 core

in vec2 vs_text;
in vec3 normal;
in vec3 FragPos;

uniform vec3 lightPos;
out vec4 gl_FragColor;



uniform vec3 objectColor;
uniform vec3 lightColor;


uniform sampler2D ourTexture;



void main()
{
    vec3 norm = normalize(normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float ambientStrength = 0.1;
        vec3 ambient = ambientStrength * lightColor;
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;
    vec3 result = (ambient + diffuse) * objectColor;
    gl_FragColor =  texture(ourTexture, vs_text) * vec4(result,1.0);
}

how can I solve the problem?

genpfault
  • 51,148
  • 11
  • 85
  • 139

1 Answers1

2

The light calculations in the fragment shader are done in world space. Therefore, you have to transform the normal vector with the normal matrix from object space to world space:

mat3 normalMatrix = transpose(inverse(mat3(model)));

normal = normalMatrix * RealNor;
FragPos = vec3(model * vec4(vs_pos, 1.0));

See Why is the transposed inverse of the model view matrix used to transform the normal vectors? and Why transforming normals with the transpose of the inverse of the modelview matrix?


Imagine a spinner and a reading lamp on a table. Your eyes are the camera. The model matrix models the spinning. This causes different sides of the spinner to be illuminated as it rotates. However, the position of the lamp does not change relative to your position.
The relative position of the lamp changes when you change your position (the position of the eyes). This can be modeled by changing the view matrix.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174