阴影贴图不适用于世界空间变换 (OpenGL)

问题描述

我正在尝试在我用 openGL 创建的 3D 世界中实现阴影贴图。 我希望能够在地图上移动,并在移动时跟随阴影,因此我需要一个光照投影矩阵,将我的世界观视锥体考虑在内。

        glm::mat4 lightProjectionMatrix = glm::ortho<float>(camera->_width * -0.5f,camera->_width * 0.5f,camera->_height * -0.5f,camera->_height * 0.5f,camera->_deep * -0.5f,camera->_deep * 0.5f);
        glm::mat4 lightViewMatrix = glm::lookAt(camera->_centroid,camera->_centroid + glm::vec3(-1,-1,0),glm::vec3(0,1,0));
        glm::mat4 lightmodelMatrix = glm::mat4(1.0);
        glm::mat4 lightMvp = depthProjectionMatrix * depthViewMatrix * depthModelMatrix;

宽度、高度、深度和质心变量来自光的正交投影的长方体。为了得到它,我使用了我的世界相机视锥角,将它们旋转到光空间中进行计算。一旦我将长方体的质心和尺寸转换为光空间,我将它们转换回世界空间。

这是我的世界投影矩阵

    _projection = glm::perspective(glm::radians(_fov),_screenRatio,_near,_far);
    _projection = glm::scale(_projection,glm::vec3(-1,1));
    _view = glm::lookAt(_cameraPos,_cameraPos + _dirLook,_cameraUp);
    _mvp = _projection * _view;

比例尺有一个左手世界轴。

现在我有了所有的东西,我应该可以有一个阴影纹理,位置如下:

    gl_Position = mvp * aPos;
    shadowCoord = lightMvp * gl_Position;

但是,我的影子没有出现。 所以我打印了一些测试用例来看看有什么问题:

auto pos = glm::vec3(50,50,300);
        auto worldPos = _mvp * glm::vec4(pos,1);
        auto Light = lightMvp * glm::vec4(pos,1);
        auto worldLight = lightMvp * worldPos;
        auto worldViewLight = lightMvp * _view * glm::vec4(pos,1);

        std::cout << "-----------" << std::endl;
        std::cout << "worldPos = " << worldPos.x << " " << worldPos.y << " " << worldPos.z << std::endl;
        std::cout << "Light = " << Light.x << " " << Light.y << " " << Light.z << std::endl;
        std::cout << "worldLight = " << worldLight.x << " " << worldLight.y << " " << worldLight.z << std::endl;
        std::cout << "worldViewLight = " << worldViewLight.x << " " << worldViewLight.y << " " << worldViewLight.z << std::endl;
worldPos = -194.856 -346.41 302.806
Light = 0.621941 0 0.177444
worldLight = 268.828 -0.0950791 67.447
worldViewLight = 1.15693 -0.250944 0.221805

这是结果。当我乘以光和世界矩阵时,我没有将值限制在 0 和 1 之间。这就是我应该拥有的。

请注意,当我没有将它们乘以世界空间时,我的地形可以正确渲染并且会出现阴影,因为它们介于 0 和 1 之间。

所以我不明白为什么我的世界矩阵会破坏它。

有什么想法或建议吗?

解决方法

当你变换到你的光空间时,你使用了一个已经变换的位置。 相反,您应该对凸轮和灯光变换使用原始顶点位置:

gl_Position = mvp * aPos;
shadowCoord = lightMvp * aPos; // DO NOT USE gl_Position;

其他注意事项:

  • 生成的坐标范围为 -1(近平面)到 +1(远平面),而不是您编写时的 0..1。
  • -1,1,1 的缩放看起来很可疑:如果你这样做,你就会从右手坐标系变成左手坐标系。如果您想让相机或灯光指向相反的方向,请不要镜像一个轴,而是将其旋转 180 度。
  • 在您的第一个代码段中,您混合使用 depthlight 前缀。复制 N 粘贴错误?
  • 您的 NEAR 和 FAR 值是多少?