c++ - 阴影贴图不适用于世界空间变换 (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,1 的缩放看起来很可疑:如果你这样做,你会从右手坐标系转到左手坐标系。如果您希望您的相机或灯光指向相反的方向,请不要镜像一个轴,而是将其旋转 180 度。
- 在您的第一个片段中,您混合了
depth
前缀light
。复制N粘贴错误? - 你的 NEAR 和 FAR 值是多少?
推荐阅读
- mingw - 来自 PATH 的应用程序在 mingw64 shell 中不可用
- javascript - 堆快照标识符是否保证单调递增?
- python-3.x - Tensorflow 合并数据集
- javascript - 在 React 中嵌套状态是不好的做法吗?
- r - 在 R 但不在 Rscript 中运行
- corda - 使用 h2.jar 远程连接到 H2 数据库
- dart - Flutter Hot Reload 不重新加载/刷新资产
- powershell - Powershell:使用函数切换脚本变量
- c - 通过 SWIG 将 Python 3 个字节输入到 C char*
- wpf - 已选择行时,WPF MVVM DataGrid DoubleClick 不起作用