Mirroring incorrectly

I am trying to make a small 3D engine for obtaining a master's degree (and for my mastery). I have a mirror image problem. (I apologize for the link to the illustration, but so far I have not enough reputation). All sources are available on my github : DWRenderer

Image of the problem

Right here, we are working with an object, but the camera is also located on the front panel and in the light. As we see, there is a reflection behind the object.

To describe the real parameters, all calculations are performed in the world space (usually ... with this problem, I doubt it). I put the camera in vec3 (0, 0, 3) position for the test, and the light is just a point in vec3 (1,2, 1, 2) represented by a cube. I am using Qt 5.4 and OpenGL 4.1 under Ubuntu with Nvidia drivers.

Here is my vertex shader:

#version 410 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;

out vec3 Normal;
out vec3 FragPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat3 normalMatrix;

void main()
{
    gl_Position = projection * view * model * vec4(position, 1.0f);
    FragPos = vec3(model * vec4(position, 1.0f));
    Normal = normalMatrix * normal;
}

And my fragment shader:

#version 410 core

out vec4 color;

in vec3 Normal;
in vec3 FragPos;

struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
};

struct Light {
    vec3 position;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

uniform Material material;
uniform Light light;

uniform vec3 viewPos;

void main()
{
    // Vectors
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(light.position - FragPos);
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);

    // Ambient
    vec3 ambient = material.ambient * light.ambient;

    // Diffuse
    float diff = clamp(dot(lightDir, norm), 0.0, 1.0);
    vec3 diffuse = diff * material.diffuse * light.diffuse;

    // Specular - The bug seems only here
    float spec = pow(clamp(dot(viewDir, reflectDir), 0.0, 1.0), material.shininess);
    vec3 specular = spec * material.specular * light.specular;

    vec3 result = (diffuse + specular + ambient);
    color = vec4(result, 1.0f);

    // For test vectors
    //color = vec4(specular, 1.0f);
}

(paintGL 16 ) ( , . "initializeGL" ):

// Draw cube
    m_cubeShader->useShaderProgram();
    GLint lightPosLoc = glGetUniformLocation(m_cubeShader->getId(), "light.position");
    GLint viewPosLoc = glGetUniformLocation(m_cubeShader->getId(), "viewPos");
    GLint matAmbientLoc  = glGetUniformLocation(m_cubeShader->getId(), "material.ambient");
    GLint matDiffuseLoc  = glGetUniformLocation(m_cubeShader->getId(), "material.diffuse");
    GLint matSpecularLoc = glGetUniformLocation(m_cubeShader->getId(), "material.specular");
    GLint matShineLoc    = glGetUniformLocation(m_cubeShader->getId(), "material.shininess");
    GLint lightAmbientLoc  = glGetUniformLocation(m_cubeShader->getId(), "light.ambient");
    GLint lightDiffuseLoc  = glGetUniformLocation(m_cubeShader->getId(), "light.diffuse");
    GLint lightSpecularLoc = glGetUniformLocation(m_cubeShader->getId(), "light.specular");
    glUniform3f(lightAmbientLoc,  0.2f, 0.2f, 0.2f);
    glUniform3f(lightDiffuseLoc,  0.5f, 0.5f, 0.5f);
    glUniform3f(lightSpecularLoc, 1.0f, 1.0f, 1.0f);
    glUniform3f(matAmbientLoc,  1.0f, 0.5f, 0.31f);
    glUniform3f(matDiffuseLoc,  1.0f, 0.5f, 0.31f);
    glUniform3f(matSpecularLoc, 0.5f, 0.5f, 0.5f);
    glUniform1f(matShineLoc,    32.0f);
    glUniform3f(viewPosLoc, 0.0f, 0.0f, 3.0f); // For testing a bug - Unresolved
    //glUniform3f(viewPosLoc, m_camera->getPosition().x, m_camera->getPosition().y, m_camera->getPosition().z);
    glUniform3f(lightPosLoc, m_lightPos.x, m_lightPos.y, m_lightPos.z);

    glm::mat4 model;
    glm::mat4 view;
    glm::mat4 projection;
    glm::mat3 normalMatrix;
    normalMatrix = glm::mat3(glm::transpose(glm::inverse(model)));
    view = m_camera->getViewMatrix();
    projection = glm::perspective(glm::radians(m_camera->getFov()), (GLfloat)m_screenWidth / (GLfloat)m_screenHeight, 0.1f, 100.0f);
    GLint normalMatrixLoc = glGetUniformLocation(m_cubeShader->getId(), "normalMatrix");
    GLint modelLoc = glGetUniformLocation(m_cubeShader->getId(), "model");
    GLint viewLoc = glGetUniformLocation(m_cubeShader->getId(), "view");
    GLint projectionLoc = glGetUniformLocation(m_cubeShader->getId(), "projection");
    glUniformMatrix3fv(normalMatrixLoc, 1, GL_FALSE, glm::value_ptr(normalMatrix));
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));

    glBindVertexArray(m_cubeVAO);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertexArray(0);

    // Draw light
    m_lightShader->useShaderProgram();

    model = glm::mat4();
    model = glm::translate(model, m_lightPos);
    model = glm::scale(model, glm::vec3(0.2f));
    modelLoc = glGetUniformLocation(m_lightShader->getId(), "model");
    viewLoc = glGetUniformLocation(m_lightShader->getId(), "view");
    projectionLoc = glGetUniformLocation(m_lightShader->getId(), "projection");
    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view));
    glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, glm::value_ptr(projection));

    glBindVertexArray(m_lightVAO);
    glDrawArrays(GL_TRIANGLES, 0, 36);
    glBindVertexArray(0);

, . // max() clamp(), . .

+4
1

, lightDir ( ) norm ( ). , . , ther ( diff - 0.0), . :

void main()
{
    // Vectors
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(light.position - FragPos);
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);

    // Ambient
    vec3 ambient = material.ambient * light.ambient;

    vec3 result = ambient;
    float dotNvLd = dot( norm, lightDir );
    if ( dotNvLd > 0.0 ) // test if normal vector not directed against vector to light position
    {
        // Diffuse
        float diff = min( dotNvLd, 1.0 );
        vec3 diffuse = diff * material.diffuse * light.diffuse;

        // Specular - The bug seems only here
        float spec = pow(clamp(dot(viewDir, reflectDir), 0.0, 1.0),   material.shininess);
        vec3 specular = spec * material.specular * light.specular;

        result = (diffuse + specular + ambient);
    }

    color = vec4(result, 1.0f);

    // For test vectors
    //color = vec4(specular, 1.0f);
}
+1

Source: https://habr.com/ru/post/1627126/


All Articles