投影变换
将摄影空间中的三维物体投影到二维胶片上,也就是Direct3D中的屏幕,这种三维到二维的变换过程就是投影变换,即从取景空间到摄影空间的变换。设三维物体在观察空间中的坐标为Pview,投影矩阵为Mproj,则顶点在投影空间中的坐标为:Pproj = Pview * Mproj
下面分别介绍两种基本的投影变换:正交投影和透视投影,以及它们在Direct3D中的实现。
1、正交投影
正交投影中,投影向量和观察平面垂直,物体坐标沿观察坐标系的z轴平行投影到观察平面上,观察点和观察平面间的距离不会影响物体的投影大小。
工程设计中的顶视图、前视图和侧视图就是典型的正交投影。与世界变换、取景变换类似,只需先生成一个投影矩阵mat_proj,然后调用下面的代码就可以设置投影矩阵:
g_device->SetTransform(D3DTS_PROJECTION, &mat_proj);
下面来看看正交投影矩阵的生成。对于正交投影来说,它的取景范围是一个长方体,只有在这个长方体中的景物才会被绘制出来。
Direct3D扩展实用库提供了函数D3DXMatrixOrthoLH(),用于创建一个正交投影矩阵,函数D3DXMatrixOrthoLH()的声明如下:
创建一个左手系正交投影矩阵。
D3DXMATRIX * D3DXMatrixOrthoLH(
D3DXMATRIX * pOut, //输出矩阵
FLOAT w, //在世界坐标系中,投影的x坐标宽度
FLOAT h, //在世界坐标系中,投影的y坐标宽度
FLOAT zn, // Minimum z-value of the view volume which is referred to as z-near.
FLOAT zf //Maximum z-value of the view volume which is referred to as z-far.
);
//示范:
D3DXMATRIXA16 matProj;
D3DXMatrixOrthoLH(&matProj, 14, 14, 0.1f, 1000.0f); //正交投影 矩阵计算
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); //设置投影变化
D3DxMatrxTooLH函数的所有参数都是摄像机空间中的距离。参数描述视图体积的尺寸。
此函数使用下面的公式来计算返回矩阵。
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, //在Y方向上的视野,以弧度表示。
FLOAT Aspect, // 宽高比,定义为视图空间宽度除以高度。
FLOAT zn, //近裁面 的Z值。
FLOAT zf //远裁面 的 z值
);
//示范:
D3DXMATRIXA16 matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/2, 1.0f, 1.0f, 1000.0f ); //D3DX_PI/2 表示90度的
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
具体计算方式:
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。
本文参考了:http://www.cppblog.com/lovedday/archive/2008/05/02/48632.html