原文地址:
http://www.cppblog.com/lovedday/archive/2008/05/02/48632.html
投影变换
将摄影空间中的三维物体投影到二维胶片上,也就是Direct3D中的屏幕,这种三维到二维的变换过程就是投影变换,即从取景空间到摄影空间的变换。设三维物体在观察空间中的坐标为 Pview ,投影矩阵为 Mproj ,则顶点在投影空间中的坐标为:
Pproj = Pview * Mproj
下面分别介绍两种基本的投影变换:正交投影和透视投影,以及它们在Direct3D中的实现。
1、正交投影
正交投影中,投影向量和观察平面垂直,物体坐标沿观察坐标系的z轴平行投影到观察平面上,观察点和观察平面间的距离不会影响物体的投影大小。
工程设计中的顶视图、前视图和侧视图就是典型的正交投影。与世界变换、取景变换类似,只需先生成一个投影矩阵mat_proj,然后调用下面的代码就可以设置投影矩阵:
g_device->SetTransform(D3DTS_PROJECTION, &mat_proj);
下面来看看正交投影矩阵的生成。对于正交投影来说,它的取景范围是一个长方体,只有在这个长方体中的景物才会被绘制出来。
Direct3D扩展实用库提供了函数D3DXMatrixOrthoLH(),用于创建一个正交投影矩阵,函数D3DXMatrixOrthoLH()的声明如下:
Builds a left-handed orthographic projection matrix.
D3DXMATRIX * D3DXMatrixOrthoLH(
D3DXMATRIX * pOut,
FLOAT w,
FLOAT h,
FLOAT zn,
FLOAT zf
);
Parameters
pOut
[in, out] Pointer to the resulting D3DXMATRIX.
w
[in] Width of the view volume.
h
[in] Height of the view volume.
zn
[in] Minimum z-value of the view volume which is referred to as z-near.
zf
[in] Maximum z-value of the view volume which is referred to as z-far.
Return Values
Pointer to the resulting D3DXMATRIX.
Remarks
All the parameters of the D3DXMatrixOrthoLH function are distances in camera space. The parameters describe the dimensions of the view volume.
The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixOrthoLH function can be used as a parameter for another function.
This function uses the following formula to compute the returned matrix.
2/w 0 0 0
0 2/h 0 0
0 0 1/(zf-zn) 0
0 0 -zn/(zf-zn) 1
2、透视投影
透视投影实现的是一个缩放、透视的投影。透视投影的特点是,距离摄像机越远的物体在投影平面上的成像越小,透视投影的取景范围是一个截头体(四棱台)。这个截头体称为取景截头体(viewing frustum),摄像机位于四棱锥的顶点。这个四棱锥被截头体的远平面和近平面分割,远近裁剪面中间的部分就是取景截头体,只有这个空间里的对象才是可见的。
透视投影矩阵的作用就是将取景截头体内的景物投影到摄像机的二维胶片上,可以利用Direct3D功能扩展库提供的D3DXMatrixPerspectiveFovLH(),构建一个透视投影矩阵:
Builds a left-handed perspective projection matrix based on a field of view.
D3DXMATRIX * D3DXMatrixPerspectiveFovLH(
D3DXMATRIX * pOut,
FLOAT fovy,
FLOAT Aspect,
FLOAT zn,
FLOAT zf
);
Parameters
pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
fovy
[in] Field of view in the y direction, in radians.
Aspect
[in] Aspect ratio, defined as view space width divided by height.
zn
[in] Z-value of the near view-plane.
zf
[in] Z-value of the far view-plane.
Return Values
Pointer to a D3DXMATRIX structure that is a left-handed perspective projection matrix.
Remarks
The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveFovLH function can be used as a parameter for another function.
This function computes the returned matrix as shown:
xScale 0 0 0
0 yScale 0 0
0 0 zf/(zf-zn) 1
0 0 -zn*zf/(zf-zn) 0
where:
yScale = cot(fovY/2)
xScale = yScale / aspect ratio
透视投影矩阵的作用是将一个取景截头体转换成一个立方体。因为截头体的近端比远端小,所以靠近摄像机的对象将被放大,而对象距离摄像机越远,其成像越小,这就是场景的透视原理。透视变换把一个取景截头体转换成一个新的坐标空间,注意,该截头体变成了一个立方体,同时,原点从场景的右上角移动到了立方体的中心。在透视变换中,x轴和z轴方向的极限都是-1和1,z轴方向对于前平面的极限是0,对后平面的极限是1。
另外,D3DX还提供了下列函数供程序员创建透视投影变换矩阵:
D3DXMatrixPerspectiveLH
Builds a left-handed perspective projection matrix
D3DXMATRIX * D3DXMatrixPerspectiveLH(
D3DXMATRIX * pOut,
FLOAT w,
FLOAT h,
FLOAT zn,
FLOAT zf
);
Parameters
pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
w
[in] Width of the view volume at the near view-plane.
h
[in] Height of the view volume at the near view-plane.
zn
[in] Z-value of the near view-plane.
zf
[in] Z-value of the far view-plane.
Return Values
Pointer to a D3DXMATRIX structure that is a left-handed perspective projection matrix.
Remarks
All the parameters of the D3DXMatrixPerspectiveLH function are distances in camera space. The parameters describe the dimensions of the view volume.
The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveLH function can be used as a parameter for another function.
This function uses the following formula to compute the returned matrix.
2*zn/w 0 0 0
0 2*zn/h 0 0
0 0 zf/(zf-zn) 1
0 0 zn*zf/(zn-zf) 0
D3DXMatrixPerspectiveRH
Builds a right-handed perspective projection matrix.
D3DXMATRIX * D3DXMatrixPerspectiveRH(
D3DXMATRIX * pOut,
FLOAT w,
FLOAT h,
FLOAT zn,
FLOAT zf
);
Parameters
pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
w
[in] Width of the view volume at the near view-plane.
h
[in] Height of the view volume at the near view-plane.
zn
[in] Z-value of the near view-plane.
zf
[in] Z-value of the far view-plane.
Return Values
Pointer to a D3DXMATRIX structure that is a right-handed perspective projection matrix.
Remarks
All the parameters of the D3DXMatrixPerspectiveRH function are distances in camera space. The parameters describe the dimensions of the view volume.
The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveRH function can be used as a parameter for another function.
This function uses the following formula to compute the returned matrix.
2*zn/w 0 0 0
0 2*zn/h 0 0
0 0 zf/(zn-zf) -1
0 0 zn*zf/(zn-zf) 0
D3DXMatrixPerspectiveFovRH
Builds a right-handed perspective projection matrix based on a field of view.
D3DXMATRIX * D3DXMatrixPerspectiveFovRH(
D3DXMATRIX * pOut,
FLOAT fovy,
FLOAT Aspect,
FLOAT zn,
FLOAT zf
);
Parameters
pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
fovy
[in] Field of view in the y direction, in radians.
Aspect
[in] Aspect ratio, defined as view space width divided by height.
zn
[in] Z-value of the near view-plane.
zf
[in] Z-value of the far view-plane.
Return Values
Pointer to a D3DXMATRIX structure that is a right-handed perspective projection matrix.
Remarks
The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveFovRH function can be used as a parameter for another function.
This function computes the returned matrix as shown.
xScale 0 0 0
0 yScale 0 0
0 0 zf/(zn-zf) -1
0 0 zn*zf/(zn-zf) 0
where:
yScale = cot(fovY/2)
xScale = yScale / aspect ratio
D3DXMatrixPerspectiveOffCenterLH
Builds a customized, left-handed perspective projection matrix.
D3DXMATRIX * D3DXMatrixPerspectiveOffCenterLH(
D3DXMATRIX * pOut,
FLOAT l,
FLOAT r,
FLOAT b,
FLOAT t,
FLOAT zn,
FLOAT zf
);
Parameters
pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
l
[in] Minimum x-value of the view volume.
r
[in] Maximum x-value of the view volume.
b
[in] Minimum y-value of the view volume.
t
[in] Maximum y-value of the view volume.
zn
[in] Minimum z-value of the view volume.
zf
[in] Maximum z-value of the view volume.
Return Values
Pointer to a D3DXMATRIX structure that is a customized, left-handed perspective projection matrix.
Remarks
All the parameters of the D3DXMatrixPerspectiveOffCenterLH function are distances in camera space. The parameters describe the dimensions of the view volume.
The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveOffCenterLH function can be used as a parameter for another function.
This function uses the following formula to compute the returned matrix.
2*zn/(r-l) 0 0 0
0 2*zn/(t-b) 0 0
(l+r)/(l-r) (t+b)/(b-t) zf/(zf-zn) 1
0 0 zn*zf/(zn-zf) 0
D3DXMatrixPerspectiveOffCenterRH
Builds a customized, right-handed perspective projection matrix.
D3DXMATRIX * D3DXMatrixPerspectiveOffCenterRH(
D3DXMATRIX * pOut,
FLOAT l,
FLOAT r,
FLOAT b,
FLOAT t,
FLOAT zn,
FLOAT zf
);
Parameters
pOut
[in, out] Pointer to the D3DXMATRIX structure that is the result of the operation.
l
[in] Minimum x-value of the view volume.
r
[in] Maximum x-value of the view volume.
b
[in] Minimum y-value of the view volume.
t
[in] Maximum y-value of the view volume.
zn
[in] Minimum z-value of the view volume.
zf
[in] Maximum z-value of the view volume.
Return Values
Pointer to a D3DXMATRIX structure that is a customized, right-handed perspective projection matrix.
Remarks
All the parameters of the D3DXMatrixPerspectiveOffCenterRH function are distances in camera space. The parameters describe the dimensions of the view volume.
The return value for this function is the same value returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveOffCenterRH function can be used as a parameter for another function.
This function uses the following formula to compute the returned matrix.
2*zn/(r-l) 0 0 0
0 2*zn/(t-b) 0 0
(l+r)/(r-l) (t+b)/(t-b) zf/(zn-zf) -1
0 0 zn*zf/(zn-zf) 0
3、w友好投影矩阵
经过顶点坐标变换后,每个顶点坐标将具有4个元素(x, y, z, w)。Direct3D使用这个w坐标在深度缓冲区和雾化效果中执行一些深度相关的运算。为了能够使用这个w坐标进行深度相关运算,要求投影矩阵必须是w友好投影矩阵(w-friendly projection matrix,也称作兼容矩阵),即投影矩阵第三行第四列的元素必须是1,以使w坐标与世界空间中顶点的z坐标相当。如果投影变换矩阵第三行第四列的元素不是1,必须将所有的矩阵元素除以投影矩阵第三行第四列元素的值,将投影矩阵变换为w友好投影矩阵。如果没有提供一个w友好投影矩阵,基于深度的雾化效果和深度缓冲就不能正确实现。
下面给出的就是从一个非w友好投影矩阵到w友好投影矩阵的转换。
Direct3D在进行以w为基础的深度计算中,需要使用w友好投影矩阵,因此即使应用程序不需要进行顶点坐标变换,也需要设置一个w友好投影矩阵。通过实用库函数D3DXMatrixPerspectiveFovLH()得到的投影矩阵通常都是w友好投影矩阵,所以通常不需要关心这个问题。