c++ - OpenGL 漫反射照明计算错误

标签 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

知道我做错了什么吗?

最佳答案

让我详细说明一下 dari 的评论。

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

现在,您在世界空间中指定了光的方向 vector LightDirection(它的方向就是您希望它在全局世界中的方向,对吗?无需使用模型以任何方式对其进行转换矩阵)。

在计算漫反射/镜面反射照明时,您希望方向/位置 vector 都位于同一坐标空间中,否则您将在不同空间之间进行计算,这会产生奇怪的结果。由于您的 LightDirectionworld-space 中,而您的 Normalview-space 中,您会得到奇怪的结果。

因此,您需要做的是解决您的问题:

  • 通过将 LightDirection 与 View 矩阵相乘(不是 modelview 因为它同时包含模型 查看矩阵)。
  • 仅从模型矩阵(而非modelview)计算您的法线矩阵,这样您的法线 vector 将最终进入世界空间就像目前的 LightDirection 一样。

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

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

关于c++ - OpenGL 漫反射照明计算错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27347790/

相关文章:

c++ - 基于像素的 3D 可视化

c++ - char&* 是什么意思?

c++ - OpenGL 三角形不会在 macOS 上呈现?

multithreading - JOGL - OpenGL 是否使用 AWT 线程来渲染图形?

OpenGL - 绘制 GUI

c++ - OpenGL:如何使光与旋转无关?

c++ - gl.h #定义灯光

c++ - 多态性在 C++ lambda 函数中不起作用

c++ - MsWord APIs - 如何将表格单元格的内容从一个转移到另一个

java - 更新基于图 block 的游戏中的光照