1. d3d的绘制流水线
局部坐标系(模型空间)、世界坐标系、观察坐标系、背面消隐、光照、裁剪、投影、视口变化、光栅化
每个3D模型都有自己的空间,空间的中心(原点)就是模型的中心。
世界空间就是物体(模型)存在的地方。世界的中心就是原点(0,0,0),注意屏幕中间的那一点不是世界空间的中心点,屏幕中间的那一点是由观察坐标系和投影的近裁剪平面决定的。
把模型放进世界空间,那么这个模型就有了一个世界坐标。那么这样不同的模型就有了相对位置。需要注意的是旋转和缩放是在模型空间中,平移是在世界空间里面。
2.D3D设计到的三个矩阵
D3D的矩阵分为三种:世界坐标矩阵(相当于opengl模型视图矩阵),视矩阵,投影矩阵。他们的设置函数都是 pDevice->SetTransfrom();
Direct3D 都使用以下顺序依次将矩阵作用于场景:(1) 世界,(2) 观察,(3) 映射。
(1).设置世界矩阵
D3DXMATRIX matWorld;
D3DXMatrixRotationY( &matWorld, timeGetTime()/150.0f );
g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
第一步是通过调用 D3DXMatrixRotationY 函数使三角形绕 y-轴 旋转。函数第一个参数是指向 D3DMATRIX 结构的指针用于返回操作结果。第二个参数是以弧度表示的旋转角度。
下一步是调用 IDirect3DDevice8::SetTransform 给 Direct3D 设备设置世界变换。SetTransform 接受的第一个参数通知 Direct3D 被设置的是哪个转换。这个例子用 D3DTS_WORLD 宏指定被设置的是世界变换。第二个参数是一个指向被设为当前变换之矩阵的指针。
(2).设置观察变换矩阵
在世界坐标系中,我们需要设置一个照相机模型来观察物体,于是又有了观察坐标系。
D3DXMATRIX *D3DXMatrixLookAtLH(
D3DXMATRIX* pOut,
CONST D3DXVECTOR3* pEye,
CONST D3DXVECTOR3* pAt,
CONST D3DXVECTOR3* pUp
);
pOut:返回的视图矩阵指针
pEye:设置摄像机的位置
pAt:设置摄像机的观察点
pUp:设置方向“上”
这个函数的后缀LH是表示左手系的意思,聪明的你一定能够猜出肯定有个叫D3DXMatrixLookAtRH的函数。
ex:
D3DXMATRIX matView;
D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0.0f, 3.0f,-5.0f ),
&D3DXVECTOR3( 0.0f, 0.0f, 0.0f ),
&D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) );
g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
(3).设置投影矩阵
在设置了观察坐标系之后,我们就需要设置投影矩阵了。投影是在观察坐标系里面进行的。
定义投影矩阵很像是定义摄像机的镜头,下面看它的函数声明:
D3DXMATRIX *D3DXMatrixPerspectiveFovLH(
D3DXMATRIX* pOut,
FLOAT fovY,
FLOAT Aspect,
FLOAT zn,
FLOAT zf
);
pOut:返回的投影矩阵指针
fovY:定义镜头垂直观察范围,以弧度为单位。对于这个参数,下面是我的理解:如果定义为D3DX_PI/4(90度角),那么就是表示以摄像机的观察方向为平分线,上方45度角和下方45度角就是摄像机所能看到的垂直范围了。嗯,可以想象一下自己的眼睛,如果可以把自己眼睛的fovY值设为D3DX_PI/2(180度角),那么我们就可以不用抬头就看得见头顶的东西了。如果设为D3DX_PI的话。。。我先编译一下试试(building…)。哈哈,结果啥也看不见。很难想象如果自己能同时看到所有方向的物体,那么将是一个怎样的画面啊。
Aspect:设置纵横比。如果定义为1,那么所看到的物体大小不变。如果定义为其它值,你所看到的物体就会变形。不过一般情况下这个值设为显示器屏幕的长宽比。(终于明白为什么有些人会说电视上的自己看起来会比较胖了……)
zn:设置摄像机所能观察到的最远距离
zf:设置摄像机所能观察到的最近距离
ex:
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f );
g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );