2.3.5光照(Lighting)
光照定义在世界坐标系中,但必须变换到视图坐标系才可使用。视图坐标系中光源给物体施加的光照大大增加了场景中物体的真实性。
2.3.6裁剪(Clipping)
我们删除那些超出了可视体范围的几何图形的过程就叫做裁剪。这会出现三种情况:
完全包含——三角形完全在可视体内,这会保持不变,并进入下一级。
完全在外——三角形完全在可视体外部,这将被删除。
部分在内(部分在外)——三角形一部分在可视体内,一部分在可视体外,则三角形将被分成两部分,可视体内的部分被保留,可视体之外的则被删除。
图2.13展示了上面三种情况:
2.3.7投影(Projection)
视图坐标系的主要任务就是将3D场景转化为2D图像表示。这种从n维转换成n-1维的过程就叫做投影。投影的方法有很多种,但是我们只对一种特殊的投影感兴趣,那就是透视投影。因为透视投影可以使离照相机越远的物体投影到屏幕上后就越小,这可以使我们把3D场景更真实的转化为2D图像。图2.14展示了一个3D空间中的点是如何通过透视投影到投影窗口上去的。
投影变换的实质就是定义可视体,并将可视体内的几何图形投影到投影窗口上去。投影矩阵的计算太复杂了,这里我们不会给出推导过程,而是使用如下的Direct3D函数通过给出平截头体的参数来求出投影矩阵。
D3DXMATRIX
*D3DXMatrixPerspectiveFovLH(
D3DXMATRIX* pOut,
//
返回的投影矩阵
FLOAT fovY,
//
用弧度表示的视野角度vertical
field of view angle in radians
FLOAT Aspect,
//
宽高比
FLOAT zn,
//
前裁剪面距离
FLOAT zf
//
后裁剪面距离
);
|
(fovY定义镜头垂直观察范围,以弧度为单位。对于这个参数,下面是我的理解:如果定义为D3DX_PI/2(90度角),那么就是表示以摄像机的观察方向为平分线,上方45度角和下方45度角就是摄像机所能看到的垂直范围了。嗯,可以想象一下自己的眼睛,如果可以把自己眼睛的fovY值设为D3DX_PI(180度角),那么我们就可以不用抬头就看得见头顶的东西了。如果设为2
x D3DX_PI的话。。。我先编译一下试试(building…)。哈哈,结果啥也看不见。很难想象如果自己能同时看到所有方向的物体,那么将是一个怎样的画面啊)
如图2.15所示视锥的描述参数。
Aspect参数为投影平面的宽高比例值,由于最后都为转换到屏幕上,所以这个比例一般设为屏幕分辨率的宽和高的比值。如果投影窗口是个正方形,而我们的显示屏一般都是长方形的,这样转换后就会引起拉伸变形。
aspectRation = screenWidth / screenHeight
我们还是通过调用IDirect3DDevice9::SetTranform方法来进行投影变换,当然,要把第一个投影类型的参数设为D3DTS_PROJECTION。下面的例子基于一个90度视角、前裁剪面距离为1、后裁剪面距离为1000的平截头体创建投影矩阵:
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(&proj, PI * 0.5f, (float)width
/ (float)height, 1.0, 1000.0f);
Device->SetTransform(D3DTS_PROJECTION, &proj);
|
2.3.8视口变换(Viewport
Transform)
视口变换主要是转换投影窗口到显示屏幕上。通常一个游戏的视口就是整个显示屏,但是当我们以窗口模式运行的时候,也有可能只占屏幕的一部分或在客户区内。视口矩形是由它所在窗口的坐标系来描述的,如图2.16。
在Direct3D中,视口矩形通过D3DVIEWPORT9结构来表示。它的定义如下:
typedef
struct _D3DVIEWPORT9 {
DWORD X;
DWORD Y;
DWORD Width;
DWORD Height;
DWORD MinZ;
DWORD MaxZ;
} D3DVIEWPORT9;
|
前四个参数定义了视口矩形与其所在窗口的关系。MinZ成员指定最小深度缓冲值,MaxZ指定最大深度缓冲值。Direct3D使用的深度缓冲的范围是0~1,所以如果不想做什么特殊效果的话,将它们分别设成相应的值就可以了。
一旦我们填充完D3DVIEWPORT9结构后,就可以如下设视口:
D3DVIEWPORT9 vp{ 0, 0, 640,
480, 0, 1 };
Device->SetViewport(&vp);
|
这样,Direct3D就会自动为我们处理视口变换。现在还是给出视口变换矩阵作为参考:
2.3.9光栅化(Rasterization)
在把三角形每个顶点转换到屏幕上以后,我们就画了一个2D三角形。光栅化是计算需要显示的每个三角形中每个点颜色值(如图2.17)。
光栅化过程是非常繁重的计算,它应该通过硬件图形处理来完成。它的处理结果就是把2D图象显示在显示器上。