为啥灯光出现在对面?
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
加载到着色器中。
【讨论】:
以上是关于为啥灯光出现在对面?的主要内容,如果未能解决你的问题,请参考以下文章