Shadowmap 适用于正射投影,但不适用于透视投影
Shadowmap works with ortho projection, but not perspective projection
我已经实现了阴影贴图,只要我使用正交投影(例如从 'sun' 获得阴影),效果就很好
但是,一旦我切换到聚光灯的透视投影,阴影贴图就不再适合我了。即使我使用完全相同的矩阵代码来创建我的(工作)透视相机投影。
是否存在一些我不知道的透视阴影贴图陷阱?
此投影矩阵(正交)有效:
const float projectionSize = 50.0f;
const float left = -projectionSize;
const float right = projectionSize;
const float bottom= -projectionSize;
const float top = projectionSize;
const float r_l = right - left;
const float t_b = top - bottom;
const float f_n = zFar - zNear;
const float tx = - (right + left) / (right - left);
const float ty = - (top + bottom) / (top - bottom);
const float tz = - (zFar + zNear) / (zFar - zNear);
float* mout = sl_proj.data;
mout[0] = 2.0f / r_l;
mout[1] = 0.0f;
mout[2] = 0.0f;
mout[3] = 0.0f;
mout[4] = 0.0f;
mout[5] = 2.0f / t_b;
mout[6] = 0.0f;
mout[7] = 0.0f;
mout[8] = 0.0f;
mout[9] = 0.0f;
mout[10] = -2.0f / f_n;
mout[11] = 0.0f;
mout[12] = tx;
mout[13] = ty;
mout[14] = tz;
mout[15] = 1.0f;
此投影矩阵(透视图)用作相机,但无法与阴影贴图一起使用:
const float f = 1.0f / tanf(fov/2.0f);
const float aspect = 1.0f;
float* mout = sl_proj.data;
mout[0] = f / aspect;
mout[1] = 0.0f;
mout[2] = 0.0f;
mout[3] = 0.0f;
mout[4] = 0.0f;
mout[5] = f;
mout[6] = 0.0f;
mout[7] = 0.0f;
mout[8] = 0.0f;
mout[9] = 0.0f;
mout[10] = (zFar+zNear) / (zNear-zFar);
mout[11] = -1.0f;
mout[12] = 0.0f;
mout[13] = 0.0f;
mout[14] = 2 * zFar * zNear / (zNear-zFar);
mout[15] = 0.0f;
考虑到它当然不现实,正射投影会按预期创建光影(见下文)。
要创建 lightviewprojection 矩阵,我只需将投影矩阵与光变换的逆矩阵相乘即可。
透视相机一切正常,但不适用于透视(聚光)灯。
而 'not working' 我的意思是:出现零光,因为不知何故,没有一个碎片落在光的视野内? (不是纹理问题,是变形问题。)
这是 GLSL 代码中齐次 W 坐标 缺失除法的情况。
不知何故,使用正交投影,不除以 W 就可以了。
使用透视投影,light-space中的坐标需要除以W
我已经实现了阴影贴图,只要我使用正交投影(例如从 'sun' 获得阴影),效果就很好
但是,一旦我切换到聚光灯的透视投影,阴影贴图就不再适合我了。即使我使用完全相同的矩阵代码来创建我的(工作)透视相机投影。
是否存在一些我不知道的透视阴影贴图陷阱?
此投影矩阵(正交)有效:
const float projectionSize = 50.0f;
const float left = -projectionSize;
const float right = projectionSize;
const float bottom= -projectionSize;
const float top = projectionSize;
const float r_l = right - left;
const float t_b = top - bottom;
const float f_n = zFar - zNear;
const float tx = - (right + left) / (right - left);
const float ty = - (top + bottom) / (top - bottom);
const float tz = - (zFar + zNear) / (zFar - zNear);
float* mout = sl_proj.data;
mout[0] = 2.0f / r_l;
mout[1] = 0.0f;
mout[2] = 0.0f;
mout[3] = 0.0f;
mout[4] = 0.0f;
mout[5] = 2.0f / t_b;
mout[6] = 0.0f;
mout[7] = 0.0f;
mout[8] = 0.0f;
mout[9] = 0.0f;
mout[10] = -2.0f / f_n;
mout[11] = 0.0f;
mout[12] = tx;
mout[13] = ty;
mout[14] = tz;
mout[15] = 1.0f;
此投影矩阵(透视图)用作相机,但无法与阴影贴图一起使用:
const float f = 1.0f / tanf(fov/2.0f);
const float aspect = 1.0f;
float* mout = sl_proj.data;
mout[0] = f / aspect;
mout[1] = 0.0f;
mout[2] = 0.0f;
mout[3] = 0.0f;
mout[4] = 0.0f;
mout[5] = f;
mout[6] = 0.0f;
mout[7] = 0.0f;
mout[8] = 0.0f;
mout[9] = 0.0f;
mout[10] = (zFar+zNear) / (zNear-zFar);
mout[11] = -1.0f;
mout[12] = 0.0f;
mout[13] = 0.0f;
mout[14] = 2 * zFar * zNear / (zNear-zFar);
mout[15] = 0.0f;
考虑到它当然不现实,正射投影会按预期创建光影(见下文)。
要创建 lightviewprojection 矩阵,我只需将投影矩阵与光变换的逆矩阵相乘即可。
透视相机一切正常,但不适用于透视(聚光)灯。
而 'not working' 我的意思是:出现零光,因为不知何故,没有一个碎片落在光的视野内? (不是纹理问题,是变形问题。)
这是 GLSL 代码中齐次 W 坐标 缺失除法的情况。
不知何故,使用正交投影,不除以 W 就可以了。
使用透视投影,light-space中的坐标需要除以W