投影转换 (Direct3D 9)
可以将投影转换视为控制相机的内部;这类似于为相机选择镜头。 这是三种转换类型中最复杂的类型。 有关投影转换的此讨论整理为以下主题。
投影矩阵通常是缩放和透视投影。 投影转换可将视锥转换为长方体形状。 由于视锥的近端小于远端,这将产生拉伸靠近相机的对象的效果;这是透视应用于场景的方式。
在视锥中,相机与视见转换空间原点之间的距离被任意定义为 D,因此投影矩阵如下图所示。
视见矩阵通过在 z 方向平移 - D 来将相机平移到原点。平移矩阵如下图所示。
平移矩阵乘以投影矩阵 (T*P) 将生成复合投影矩阵,如下图所示。
透视转换可将视锥转换到新的坐标空间中。 请注意,视锥将变成长方体,原点将从场景的右上角移动到中间,如下图所示。
在透视转换中,x 方向和 y 方向的极限分别为 -1 和 1。 z 方向的极限对于前平面为 0,对于后平面为 1。
此矩阵将根据从相机到近剪裁平面的指定距离平移和缩放对象,但它不会考虑视场 (fov),并且它为该距离内的对象生成的 z 值可能几乎相同,从而加大了深度比较的难度。 以下矩阵将解决这些问题,该矩阵将调整顶点以实现视区的纵横比,从而使其成为透视投影的明智之选。
在此矩阵中,Zₙ 是仅剪裁平面的 z 值。 变量 w、h 和 Q 具有以下含义。 请注意,fovw 和 fovₖ 表示视区的水平和垂直视场(以弧度为单位)。
对于你的应用程序,使用视场角度来定义 x 和 y 缩放系数可能没有使用视区的水平和垂直维度(在相机空间中)方便。 随着数学结果被解出,涉及 w 和 h 的以下两个方程将使用视区的维度并等效于上述方程。
在这些公式中,Zₙ 表示近剪裁平面的位置,Vw 和 Vₕ 变量表示视区在相机空间中的宽度和高度。
对于 C++ 应用程序,这两个维度直接对应于 D3DVIEWPORT9 结构的 Width 和 Height 成员。
无论你决定使用哪个公式,请务必将 Zₙ 的值设置得尽可能大,因为非常靠近相机 z 值变化不会很大。 这在某种程度上增加了使用 16 位 z 缓冲区的深度比较得复杂度。
与世界和视图转换一样,调用 IDirect3DDevice9::SetTransform 方法来设置投影转换。
设置投影矩阵
以下 ProjectionMatrix 示例函数设置前后剪裁平面,以及视图角度的水平和垂直范围。 视图的字段应小于 pi 弧度。
D3DXMATRIX
ProjectionMatrix(const float near_plane, // Distance to near clipping
// plane
const float far_plane, // Distance to far clipping
// plane
const float fov_horiz, // Horizontal field of view
// angle, in radians
const float fov_vert) // Vertical field of view
// angle, in radians
{
float h, w, Q;
w = (float)1/tan(fov_horiz*0.5); // 1/tan(x) == cot(x)
h = (float)1/tan(fov_vert*0.5); // 1/tan(x) == cot(x)
Q = far_plane/(far_plane - near_plane);
D3DXMATRIX ret;
ZeroMemory(&ret, sizeof(ret));
ret(0, 0) = w;
ret(1, 1) = h;
ret(2, 2) = Q;
ret(3, 2) = -Q*near_plane;
ret(2, 3) = 1;
return ret;
} // End of ProjectionMatrix
创建矩阵后,使用指定D3DTS_PROJECTION的 IDirect3DDevice9::SetTransform 对其进行设置。
D3DX 实用工具库提供以下函数来帮助你设置投影矩阵。
- D3DXMatrixPerspectiveLH
- D3DXMatrixPerspectiveRH
- D3DXMatrixPerspectiveFovLH
- D3DXMatrixPerspectiveFovRH
- D3DXMatrixPerspectiveOffCenterLH
- D3DXMatrixPerspectiveOffCenterRH
W 友好投影矩阵
Direct3D 可使用已由世界矩阵、视图矩阵和投影矩阵转换的顶点的 w 分量在深度缓冲区或雾效果中执行基于深度的计算。 这样的计算要求你的投影矩阵将 w 规范化为与世界空间 z 等效。 简而言之,如果投影矩阵包含不为 1 的 (3,4) 系数,你必须以 (3,4) 系数的倒数为缩放度来缩放所有系数以生成正确的矩阵。 如果你不提供符合要求的矩阵,则雾效果和深度缓冲无法正确应用。
下图显示了不合要求的投影矩阵,相同的矩阵已缩放,以便启用相对于眼睛的雾化。
在上述矩阵中,所有变量都假定为非零。 有关眼睛相对雾的详细信息,请参阅 眼睛相对深度与基于 Z 的深度。 有关基于 w 的深度缓冲的信息,请参阅 深度缓冲区 (Direct3D 9) 。
Direct3D 在其基于 w 的深度计算中使用当前设置的投影矩阵。 因此,应用程序必须设置符合要求的投影矩阵才能获得所需的基于 w 的功能,即使它们不使用 Direct3D 进行转换也是如此。
相关主题