OpenGL漫反射光计算错误

时间:2014-12-07 21:02:23

标签: c++ opengl lighting

我有简单的场景,涉及旋转立方体和定向(漫反射)光源,但我似乎没有得到正确的光照数学。

我从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

知道我做错了什么吗?

1 个答案:

答案 0 :(得分:2)

让我详细介绍一下达瑞的评论。

您的法向量乘以从view*model矩阵(在您的应用程序中称为modelview)派生的普通矩阵。将顶点与模型矩阵相乘将它们从局部空间转换为世界空间,并将世界空间中的顶点与视图矩阵相乘转换它们到视图空间坐标。在您的情况下,您使用模型视图矩阵转换了法线向量;这意味着您的法线向量位于视图空间(它们的方向,从观察者的角度来看:相机)。

现在,你在世界空间中指定了光的方向向量LightDirection(它的方向是你想要它在全球世界中的方式吗?不需要用任何方式改变它模型矩阵)。

计算漫反射/高光照明时,您希望方向/位置矢量全部位于同一坐标空间中,否则您将在不同空间之间进行计算,从而产生奇怪的结果。由于您的LightDirection位于世界空间,而Normal位于视图空间,您会得到奇怪的结果。

您需要做的是解决您的问题:

  • LightDirection转换为视图空间,方法是将其与视图矩阵(不是modelview相乘,因为它包含模型视图矩阵)。
  • 仅从模型矩阵(而不是modelview)计算您的正常矩阵,因此您的法线向量将最终位于 world-space 中,就像{{{ 1}}目前是。

重要的是两个矢量都在同一个空间(可以是世界或视图,无论你喜欢什么)。

注意这适用于当您想要在物体静止时让相机移动的印象时(允许您移动到物体的未点亮的一侧);请参阅下面的Reto Koradi的评论。