每日一语:
当一切都安于现状后,这个社会就无法发展,也就无法从原始社会发展到现代社会,对于人也是一样,如果我们一直安于现状,就无法有更大更好的发展,我们不要想着,一直可以过安逸的生活,程序员这个职业,一直就是不进则退,知识更新换代的速度极快,很多公司都倒在这样的飞快的互联网时代,更别说人了。当你的知识已被社会淘汰,想必你被公司淘汰也就不远了,我们应该不断的改变自己,挑战自己,在变化中,不断的定位自己,找到机遇。
正文:
模型表示:
场景是物体或模型的集合。任何物体都可以用三角形网格逼近表示。三角形网格是构建物体模型的基本单元。Direct3D除了提供三角形图元外,也支持线和点图元。
一个多边形中相邻两边的交汇点称为顶点。描述三角形单元时,我们需要指定该三角形单元的3个顶点的位置。而描述物体时,我们需要指定构成该物体的三角形单元列表。
在Direct3D中,顶点除了包含空间信息外,还可以包含其他的附加属性。例如,顶点可以有颜色属性,也可以有法线属性,Direct3D允许我们自行定义顶点的格式。
例如:
struct ColorVertex{
float _x,_y,_z;位置
DWORD _color;颜色
};
struct NormalTexVertex{
float _x,_y,_z;位置
float _nx,_ny,_nz;法线
float _u,_v;纹理
};
灵活顶点格式(Flexible Vertex Format,FVF),上面的可以描述为;
#define FVF_COLOR (D3DFVF_XYZ | D3DFVF_DIFFUSE}
#define FVF_NORMAL_TEX(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1)
三角形单元:
三角形单元是3D物体的基本组成部分。为了构建一个物体,需要创建一个描述物体形状和轮廓的三角形单元列表。三角形单元列表包含了我们所希望绘制的每个独立三角形的数据。例如为了一个矩形,我们将其分解为两个三角形单元,并指定每个三角形单元的顶点。
索引:
通常,构成一个3D物体的众多三角形单元之间会共享许多公共顶点。为解决该问题,我们引入索引的概念。原理如下,我们创建一个顶点列表(Vertex list)和一个索引列表(index list).顶点列表包含了全部独立顶点,索引列表包含了指向顶点列表的索引,这些索引规定了为构建三角形单元,各顶点应按何种方式来组织。
我们来看矩形的例子。
Vertex vertexlist[4] = {v0,v1,v2,v3};
WORD indexlist[6] = {0,1,2,0,2,3};
虚拟摄像机:
摄像机指定了场景对观察者的可见部分,即我们将依据哪部分3D场景来创建2D图像。在世界坐标系中,摄像机有一定的位置和方向,定义了可见的空间体积。
用几何学中的术语讲,上述的空间体积是一个平截头体。在3D图形学中也可称为视域体或视截体。采用视域体的主要原因是显示屏为矩形,那些位于之外的物体是看不见的,在进一步处理时,应该将其丢弃。丢弃这类数据的运算过程称为裁剪。
投影窗口:
投影窗口是一个2D区域,位于视域体中的3D几何体通过投影映射到改区域中,便创建了3D场景的2D表示。很重要的一点是,矩形投影窗口在X和Y方向坐标的最小值是min={-1,-1},最大值是max={1,1}。
绘制流水线:
绘制流水线的流程:
局部坐标系-》世界坐标系-》观察坐标系-》背面消隐-》光照-》裁剪-》投影-》视口坐标系-》光栅化
局部坐标系:
局部坐标系或建模坐标系,是用于定义构成物体的三角形单元列表的坐标系。采用局部坐标系的优势体现在它可以简化建模过程。在物体的局部坐标系中建模要比直接在世界坐标系中容易得多。例如,局部坐标系允许我们构建模型时无需考虑位置,大小或相对于场景中其他物体的朝向。
世界坐标系:
构建各种物体模型时,每个模型都位于其自身的局部坐标系中。我们还需要将这些物体组织在一起构成世界坐标系中的场景。位于局部坐标系中的物体通过一个称为世界变换的运算过程变换到世界坐标系中,该变换通常包括平移,旋转以及比例运算,分别用于设定该物体在世界坐标系中的位置,方向以及模型的大小。
观察坐标系:
在世界空间中,几何体和摄像机都是相对世界坐标系来定义的。但是,当摄像机的位置和朝向任意时,投影变换即其他类型的变换就略显困难或效率不高。为了简化运算我们将摄像机变换至世界坐标系的原点,并将其旋转,使摄像机的光轴与世界坐标系z轴的正方向一致。同时,世界空间中的所有几何体都随着摄像机一同进行变换,以保证摄像机的视场恒定。这种变换称为取景变换,我们称变换后的几何体位于观察坐标系中。
背面消隐:
每个多边型都有两个侧面,我们将其中的一个侧面标记为正面,另一个侧面标记为背面。通常,多边型的背面是不可见的。这是由于场景中的多数物体都是封闭体,而且摄像机总是禁止进入物体内部的实体空间的。当然为了,实现背面消隐,Direct3D需要区分哪些多边形是正面超向的,哪些是背面朝向的。默认状态下,Direct3D认为顶点排序为顺时针(观察坐标系)的三角形单元是正面朝向的,顶点排列顺序是逆时针的三角形单元是背面朝向的。
Device->SetRenderState(D3DRS_CULLMODE,Value);
Value可取以下值:
D3DCULL_NONE 完全禁用背面消隐
D3DCULL_CW 只对顺时针绕序的三角形单元进行消隐
D3DCULL_CCW 默认值,只对逆时针绕序的三角形单元进行消隐
光照:
光源是世界坐标系中定义的,但必须仅取景变换至观察坐标系方可使用。在观察坐标系中,光源照亮了场景中的物体,从而可以获得较为逼真的显示效果。
裁剪:
现在我们想将那些位于视域体外的几何体剔除掉,这个过程称为裁剪。一个三角形单元与视域体的相对位置关系有以下3种。
完全在内部 如果三角形单元完全在视域体内,便被保留并转向下一个阶段的处理。
完全在外部 如果三角形单元完全在视域体外,将被剔除。
部分在内: 在外的剔除,在内的保留。
投影:
观察坐标系中,我们的任务是获取3D场景的2D表示。从n维变换为n-1维的过程称为投影。实现投影的方式有很多种,但是我们只对其中的一种感兴趣,即透视投影。透视投影会产生透视缩短的视觉效果,即近大远小。这类投影使得我们可以用2D图像表示3D场景。
视口变换:
视口变换的任务是将顶点坐标从投影窗口转换到屏幕的一个矩形区域中,该矩形区域称为视口。在游戏中,视口通常是整个矩形屏幕区域。但视口也可以是屏幕的一个子区域或客户区。
D3DVIEWPORT9 vp={0,0,640,480,0,1};
Device->SetViewport(&vp);
光栅化:
顶点坐标变换为屏幕坐标后,我们就有了一个2D三角形单元的列表。光栅化的任务是为了绘制每个三角形单元,如何计算构成三角形单元的每个像素的颜色值。