您的位置:首页 > 编程语言

【阅读笔记之四】《DIRECTX.9.0.3D游戏开发编程基础》绘制流水线

2012-10-19 00:00 567 查看
绘制流水线

绘制流水线的功能是,在给定的3D场景和指定观察方向的虚拟摄像机的几何描述时,创建一幅2D图像。

1. 模型表示
在现实生活中,任何物体都可以用三角形网格逼近表示。三角形网格是建立物体模型的基本单元。注:线和点图元对于3D图形建模作用不大,这里不讨论。

1) 顶点格式
Direct3D允许自定义顶点格式。一般以结构体表示顶点格式。在创建好顶点格式之后,需要利用灵活顶点格式FVF(Flexible Vertex Format)标记的组合来描述顶点的组织结构。定义FVF时需要遵循的约定是:FVF标记的指定顺序必须与顶点结构中相应类型数据顺序保持一致。
2)三角形单元
三角形图元是3D图形的基本组成部分。为了构建一个物体,需要创建一个描述物体形状和轮廓的三角形单元列表。这个列表包含了我们所希望绘制的每个独立三角形的数据。三角形各顶点的指定顺序非常重要,我们称其为绕序。
3)索引
在利用三角形图元建立物体模型时,可能会有很多顶点是重合的。索引就是为了解决这个问题。方法如下:我们创建一个顶点列表(vertex list)和一个索引列表(index list),顶点列表包含了全部独立顶点,索引列表包含了指向所有顶点列表的索引(比较拗口...),这些索引规定了构建三角形图元各顶点应该按照什么样的方式组合在一起。示例如下:
//顶点列表的定义
Vertex vertexlist[4]={v1, v2, v3, v4};

//索引列表的定义
DWORD indexlist[6]={0,1,2,
0,2,3};
//第一个三角形由顶点v1,v2,v3组成
//第一个三角形由顶点v0,v2,v3组成


2.
虚拟摄像机

摄像机指定了场景对观察者的可见部分,即我们依据那部分3D场景来创建2D图像。下图是一个虚拟摄像机的模型。



在3D图形学中,上述几何体称为“视域体”。采用视域体的主要原因是显示是矩形。那些视域体之外的部分是不可见的,因此需要丢弃,丢弃的过程称为裁剪(clipping)。投影窗口是一个2D区域,位于视域体的3D图形通过投影映射到该区域,便创建了2D图形。

3.
绘制流水线

在建立好3D场景的几何描述并设置好虚拟摄像机之后,下面就是在显示器中建立2D场景。下图为大致流程:



1) 局部坐标系
局部坐标系或者建模坐标系,用于定义物体的三角形单元列表的坐标系。采用局部坐标系的有点在于简化了建模过程。
2) 世界坐标系
构建物体模型时是使用局部坐标系。但要把这些物体组织在一起就需要世界坐标系。位于局部坐标系的物体通过一个世界变换(world transform)的运算变换到世界坐标系。世界变换用一个矩阵来表示,并由Direct3D呼叫IDirect3DDevice9::SetTransform方法加以利用。
//
//让一个立方体中心位于世界坐标系中点(-3,2,6)
//让一个球体中心位于点(5,0,-2)
//
//建立立方体世界变换矩阵
D3DXMATRIX cubeWorldMatrix;
D3DMatrixTranslation(&cubeWorldMatrix,-3.0f,2.0f,6.0f);

//建立球体世界变换矩阵
D3DXMATRIX sphereWorldMatrix;
D3DMatrixTranslation(&sphereWorldMatri,5.0f,0.0f,-2.0f);

//设置变换
Device->SetTransform(D3DTS_WORLD,&cubeWorldMatrix);
drawCube();

Device->SetTransform(D3DTS_WORLD,&sphereWorldMatrix);
drawSphere();

3) 观察坐标系
在世界空间中,几何体和摄像机都是相对世界坐标系定义的。但是,当摄像机的位置和朝向任意时,投影变换和其他类型的变换就略显困难或效率不高。为了简化运算,我们将摄像机变换至世界坐标系的原点,并将其旋转,使摄像机光轴和世界坐标的Z轴正方向一致。同时,世界坐标系的所有几何体随摄像机一同变换,使得其视场恒定。这种变换称为取景变换,变换后的几何体位于观察坐标系中。
4) 背面消隐
每个图形都正面和背面。背面要求是不可见的。即摄像机禁止进入内部实体空间。为了实现背面消隐,Direct3D需要知道哪些多边形是正面朝向的还是背面朝向的。默认状态下,Direct3D认为顶点排列顺序为顺时针的三角形单元是正面朝向的(在观察坐标系中)。
5) 光照
光源是在世界坐标系中定义的,但必须经过取景变换至观察坐标系方向方可使用。
6) 裁剪
把视域体之外的几何体剔除掉即为裁剪。一个三角形单元与视域体的位置关系有三种,分别为完全在内部、完全在外部和部分在内(部分在外)。
7) 投影
观察坐标系中,我们的任务是获取3D场景的2D表示。从n维变换到n-1维的过程称为投影。我们这里讲透视投影(投影的一种)。透视投影会产生“透视缩短”的效果,即近大远小。这类投影可以使我们可以用2D图像表示3D场景。投影变换定义了视域体,并负责将视域体中的几何体投影到窗口中,因此投影矩阵比较复杂。如下函数是依据视域体的描述信息创建一个投影矩阵。
//
//创建投影矩阵的函数
//
D3DXMATRIX *D3DXMatrixPerspectiveFovLH{
D3DXMATRIX & pOut,  //返回投影矩阵
FLOAT fovY,         //
FLOAT Aspect,       //纵横比=width/height
FLOAT zn,           //distance to near plane
FLOAT zf            //distance to far plane
};

8) 视口变换
视口变换(viewport transform)的任务是将顶点坐标转换到屏幕的一个矩形区域中,该矩形区域被称为视口。在Direct3D中,视口用结构D3DVIEWPORT9描述。
//
//D3DVIEWPORT9结构
typedef struct D3DVIEWPORT9{
DWORD x;     //视口矩形相对其父窗口的位置和大小
DWORD y;
DWORD Width;
DWORD Height;
DWORD MinZ;   //深度缓存中的最小深度值
DWORD MaxZ;   //深度缓存中的最大深度值
}D3DVIEWPORT9;

//
//一旦填充好D3DVIEWPORT9结构,就可以设置视口了
//Direct3D将会自动为我们完成视口变换
//
D3DVIEWPORT9 vp = {0, 0, 640, 480, 0, 1};
Device->SetViewport(&vp);

9) 光栅化
顶点坐标变换为屏幕坐标后,我们就有一个2D三角形图元列表。光栅化的任务就是绘制每个三角形图元,如何计算构成三角形图元的每个像素的颜色值。光栅化的最终结果显示在屏幕上。

本章结束。

————Josh 2012年10月18日
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐