首页 > 解决方案 > 为什么灯光出现在对面?

问题描述

我正在尝试使用教程构建照明。但是,照明出现在人体物体的错误一侧,我不知道为什么。

每个三角形创建法线。三角形的顶点基本上具有相同的法线:

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

主循环:

    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();

从物体前面看:

在此处输入图像描述

从物体背面看:

在此处输入图像描述

编辑: 为了调试,我从主循环中删除了对象旋转矩阵:

 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.setUniform("transform", phantomtTransformation);

并更改片段着色器中的行

frag_color = vec4(result, vert_color.w);

frag_color = vec4(Normal, vert_color.w);

为了可视化正常值。结果,我注意到当相机改变位置时,幻影也会改变颜色,这意味着正常值也在改变。

在此处输入图像描述

在此处输入图像描述

标签: c++openglglm-mathlight

解决方案


我认为您的问题的原因是您没有将模型转换应用于法线向量。由于您绝对不想倾斜它们,因此您必须为您的法线创建一个特殊的矩阵。

正如您提到的教程中进一步解释的那样,矩阵可以这样构造

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

在你的顶点着色器中。 但是,我强烈建议您改为在应用程序代码中计算矩阵,因为您将在上面的示例中按顶点计算它。由于您使用的是 glm 库,因此它看起来像这样:

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

然后,您可以将新model_normal矩阵作为uniform mat3.


推荐阅读