我有简单的场景,涉及旋转立方体和定向(漫反射)光源,但我似乎没有得到正确的光照数学。
我从this教程:
加载obj文件中的顶点和法线我的一些应用程序代码:
glm::mat4 modelview = ...
glm::mat4 projection = glm::perspective(60.0f, 16.0f/9.0f, 0.1f, 100.0f);
glm::mat4 MVP = projection * modelview;
glm::mat3 NormalMatrix = glm::transpose(glm::inverse(glm::mat3(modelview)));
glUniformMatrix4fv(MVP_location, 1, GL_FALSE, &MVP[0][0]);
glUniformMatrix3fv(NormalMatrix_location, 1, GL_FALSE, &NormalMatrix[0][0]);
glDrawArrays(GL_TRIANGLES, 0, 36);
顶点着色器:
#version 430
in vec3 position;
in vec3 in_normal;
uniform mat4 MVP;
uniform mat3 NormalMatrix;
out vec3 Normal;
out vec4 Color;
void main()
{
gl_Position = MVP * vec4(position, 1.0);
Color = vec4(clamp(position, 0.0, 1.0), 1.0); //based on vertex position
Normal = normalize(NormalMatrix * in_normal);
}
片段着色器:
#version 430
const vec3 Ambient = vec3(0.15, 0.15, 0.15);
const vec3 LightDirection = normalize(vec3(1.0, 0.0, 1.0));
const vec3 LightColor = vec3(1.0, 1.0, 1.0);
const float Shininess = 20.0;
const float Strength = 5.0;
in vec3 Normal;
in vec4 Color;
out vec4 FragColor;
void main()
{
FragColor = Color;
float diffuse = max(0.0, dot(Normal, LightDirection));
vec3 scatteredLight = Ambient + LightColor * diffuse;
vec3 rgb = min(FragColor.rgb * scatteredLight, vec3(1.0));
FragColor = vec4(rgb, Color.a);
}
这就是我得到的: my fail
知道我做错了什么吗?
答案 0 :(得分:2)
让我详细介绍一下达瑞的评论。
您的法向量乘以从view*model
矩阵(在您的应用程序中称为modelview
)派生的普通矩阵。将顶点与模型矩阵相乘将它们从局部空间转换为世界空间,并将世界空间中的顶点与视图矩阵相乘转换它们到视图空间坐标。在您的情况下,您使用模型和视图矩阵转换了法线向量;这意味着您的法线向量位于视图空间(它们的方向,从观察者的角度来看:相机)。
现在,你在世界空间中指定了光的方向向量LightDirection
(它的方向是你想要它在全球世界中的方式吗?不需要用任何方式改变它模型矩阵)。
计算漫反射/高光照明时,您希望方向/位置矢量全部位于同一坐标空间中,否则您将在不同空间之间进行计算,从而产生奇怪的结果。由于您的LightDirection
位于世界空间,而Normal
位于视图空间,您会得到奇怪的结果。
您需要做的是解决您的问题:
LightDirection
转换为视图空间,方法是将其与视图矩阵(不是modelview
相乘,因为它包含模型和视图矩阵)。modelview
)计算您的正常矩阵,因此您的法线向量将最终位于 world-space 中,就像{{{ 1}}目前是。重要的是两个矢量都在同一个空间(可以是世界或视图,无论你喜欢什么)。
注意这适用于当您想要在物体静止时让相机移动的印象时(允许您移动到物体的未点亮的一侧);请参阅下面的Reto Koradi的评论。