阴影贴图不适用于世界空间变换 (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, 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看起来很可疑:如果你这样做,你从右手坐标系坐标系到左手坐标系坐标系。如果你想让你的相机或灯光指向相反的方向,不要反射一个轴,而是把它旋转180度。
  • 在您的第一个代码片段中,您混合depthlight前缀。复制粘贴错误?
  • 你的NEAR和FAR值是多少?

最新更新