Почему свет появляется с противоположной стороны? - PullRequest
0 голосов
/ 13 июля 2020

Я пытаюсь создать освещение, используя этот учебник. Однако освещение появляется не с той стороны от человеческого объекта, и я не знаю почему.

Нормали были созданы для каждого треугольника. Вершины треугольника в основном имеют одну и ту же нормали:

glm::vec3 calculateNormal(glm::vec3 vertice_1, glm::vec3 vertice_2, glm::vec3 vertice_3)
{
    glm::vec3 vector_1 = vertice_2 - vertice_1;
    glm::vec3 vector_2 = vertice_3 - vertice_1;
    return glm::normalize(glm::cross(vector_1, vector_2));
}

Вот код для вершинного шейдера:

#version 330 core

layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 normal;
out vec4 vert_color;
out vec3 Normal;
out vec3 FragPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 transform;
uniform vec4 color;

void main()
{
    vert_color = color;
    gl_Position = projection * view * model * transform * vec4(pos.x, pos.y, pos.z, 1.0);
    FragPos = vec3(model * transform *  vec4(pos, 1.0));
    Normal = normal;
}

Фрагментный шейдер:

#version 330 core

uniform vec3 cameraPos;
uniform vec3 lightPos;
uniform vec3 lightColor;

in vec4 vert_color;
in vec3 FragPos;
in vec3 Normal;
out vec4 frag_color;

void main()
{
    float ambientStrength = 0.1;
    float specularStrength = 0.5;
    vec3 ambient = ambientStrength * lightColor;

    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(Normal, lightDir), 0.0);
    vec3 diffuse = diff * lightColor;

    vec3 viewDir = normalize(cameraPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, Normal);

    float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
    vec3 specular = specularStrength * spec * lightColor; 

    vec3 result = (ambient + diffuse + specular) * vec3(vert_color.x, vert_color.y, vert_color.z);
    frag_color = vec4(result, vert_color.w);
}

Main l oop:

    wxGLCanvas::SetCurrent(*glContext);
    glClearDepth(1.0f);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);

    glm::mat4 model, view, projection;
    model = glm::translate(model, modelPos); // modelPos is 
    view = fpsCamera->getViewMatrix();
    projection = fpsCamera->getProjectionMatrix(windowWidth, windowHeight);
    color = glm::vec4(0.310f, 0.747f, 0.185f, 1.0f);
    glm::vec3 lightPos = glm::vec3(0.0f, 1.0f, 0.0f);
    glm::vec3 lightColor = glm::vec3(1.0f, 1.0f, 1.0f);

    glm::mat4 phantomtTransformation;
    phantomtTransformation = glm::rotate(phantomtTransformation, - glm::pi<float>() / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f));
    phantomtTransformation = glm::rotate(phantomtTransformation, - glm::pi<float>() , glm::vec3(0.0f, 0.0f, 1.0f));
    
    ShaderProgram shaderProgram;
    shaderProgram.loadShaders("Shaders/phantom.vert", "Shaders/phantom.frag");

    glClearStencil(0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    shaderProgram.use();
    shaderProgram.setUniform("transform", phantomtTransformation);
    shaderProgram.setUniform("model", model);
    shaderProgram.setUniform("view", view);
    shaderProgram.setUniform("projection", projection);
    shaderProgram.setUniform("color", color);
    shaderProgram.setUniform("lightColor", lightColor);
    shaderProgram.setUniform("lightPos", lightPos);
    shaderProgram.setUniform("cameraPos", fpsCamera->getPosition());

    
    glStencilMask(0xFF); // Write to stencil buffer
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    glStencilFunc(GL_ALWAYS, 0, 0xFF);  // Set any stencil to 0

    glStencilFunc(GL_ALWAYS, 1, 0xFF); // Set any stencil to object ID
    m_pantomMesh->draw();
    glStencilFunc(GL_ALWAYS, 0, 0xFF);  // Set any stencil to 0        // no need for testing

    glFlush();
    wxGLCanvas::SwapBuffers();

Вид спереди объекта:

enter image description here

View from back of the object:

enter image description here

EDIT: In order to debug I removed object rotation matrix from main loop:

 glm::mat4 phantomtTransformation;
    phantomtTransformation = glm::rotate(phantomtTransformation, - glm::pi() / 2.0f, glm::vec3(1.0f, 0.0f, 0.0f));
    phantomtTransformation = glm::rotate(phantomtTransformation, - glm::pi() , glm::vec3(0.0f, 0.0f, 1.0f));
 
shaderProgram.setUniform("transform", phantomtTransformation);

and changed line in fragment shader from

frag_color = vec4(result, vert_color.w);

to

frag_color = vec4(Normal, vert_color.w);

in order to visualize Normal values. As a result I noticed that when camera changes position phantom also changes color which means that normal values are also changing.

enter image description here

введите описание изображения здесь

1 Ответ

0 голосов
/ 13 июля 2020

Я думаю, что причина вашей проблемы в том, что вы не применяете преобразование модели к своим нормальным векторам. Поскольку вы определенно не хотите их перекосить, вам придется создать специальную матрицу для ваших нормалей.

Как будет объяснено ниже в упомянутом вами руководстве, матрица может быть построена следующим образом

Normal = mat3(transpose(inverse(model))) * aNormal;

в вершинном шейдере. Однако , я настоятельно рекомендую вам вместо этого вычислить матрицу в коде вашего приложения, поскольку в приведенном выше примере вы будете вычислять ее для каждой вершины. Поскольку вы используете библиотеку glm, она будет выглядеть так:

glm::mat3 model_normal = glm::mat3(glm::transpose(glm::inverse(model)));

Затем вы можете загрузить новую матрицу model_normal в шейдер как uniform mat3.

...