为啥灯光出现在对面?

Posted

技术标签:

【中文标题】为啥灯光出现在对面?【英文标题】:Why lighting appears on opposite side?为什么灯光出现在对面? 【发布时间】:2020-07-12 22:16:56 【问题描述】:

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

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

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

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

【问题讨论】:

在您的顶点着色器中,您没有对法线应用任何变换。它只是说正常=正常。您应该通过模型旋转值旋转法线方向(因为它是一个方向,所以没有缩放或平移)我现在没有时间彻底阅读这个,但我敢打赌这是问题的根源 @Joey ,我确实将法线向量与旋转矩阵相乘,但没有帮助。 Normal = transform * normal; 【参考方案1】:

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

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

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

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

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

然后您可以将新的model_normal 矩阵作为uniform mat3 加载到着色器中。

【讨论】:

以上是关于为啥灯光出现在对面?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我一打开vray渲染器就渲染出来一片黑

灯光为啥没有阴影效果?

为啥我在3D中打灯光没有阴影效果

vray 打了灯光,为啥渲染全黑的

unity如何更改烘焙灯光阴影的颜色

unitu为啥hdr版添加灯光不亮