c++ - 为什么灯光出现在对面?
问题描述
我正在尝试使用本教程构建照明。但是,照明出现在人体物体的错误一侧,我不知道为什么。
每个三角形创建法线。三角形的顶点基本上具有相同的法线:
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);
为了可视化正常值。结果,我注意到当相机改变位置时,幻影也会改变颜色,这意味着正常值也在改变。
解决方案
我认为您的问题的原因是您没有将模型转换应用于法线向量。由于您绝对不想倾斜它们,因此您必须为您的法线创建一个特殊的矩阵。
正如您提到的教程中进一步解释的那样,矩阵可以这样构造
Normal = mat3(transpose(inverse(model))) * aNormal;
在你的顶点着色器中。 但是,我强烈建议您改为在应用程序代码中计算矩阵,因为您将在上面的示例中按顶点计算它。由于您使用的是 glm 库,因此它看起来像这样:
glm::mat3 model_normal = glm::mat3(glm::transpose(glm::inverse(model)));
然后,您可以将新model_normal
矩阵作为uniform mat3
.
推荐阅读
- python-3.x - 根据列值python制作dtaframe的子集
- python - 现有 Oracle 表上的 Django 模型设置
- spring-boot - Spring Boot webflux TEXT_EVENT_STREAM_VALUE 不起作用
- python - 修改神经网络以一次预测 3 个示例
- karate - 如何在空手道中为 SOAP 创建动态有效负载
- python - Groupby 并在 PySpark 数据框中创建一个新列
- javascript - 您的客户发出的请求过大
- google-analytics - google anayltics 如何了解 Google 广告?
- c++ - 避免默认参数中的异常
- rest - 在 Domino 9.0.1 FP 10 中启用/配置 CORS