Direct3D 初涉:绘制流水线
绘制流水线(rendering pipeline):从 3D 场景到 2D 场景,必须实施的一系列运算。
局部坐标系->世界坐标系->观察坐标系->背面消隐->光照->裁剪->投影->视口坐标系->光栅化
1. 局部坐标系(local space)
局部坐标系(local space)或者建模坐标系(modeling space),是用于建立构成物体的三角形单元列表的坐标系。采用局部坐标系的优势体现在它可以简化建模过程。
个人理解:局部坐标系即以物体本身建模,假如你要为一个茶壶建模,那么局部坐标系的原点可以为茶壶中心;再如你要为一个球体建模,那么局部坐标系的原点可以为球的中心。
2. 世界坐标系 (world space)
将所有建立在局部坐标系上的物体组织在一起构成世界坐标系。将局部坐标系变换到世界坐标系中,称为世界变换(world transform)。
Direct3D 通过 IDirect3DDevice9::SetTransform 方法进行变换。
3. 观察坐标系
为了简化运算,我们将摄像头变换至世界坐标系的原点,并将其旋转,使摄像机的光轴与世界坐标系 z 轴方向一致。(个人理解:也就是相当于人站在坐标原点向 z 轴方向看) 这种变换称为取景变换(view space transformation),变换后的几何体位于观察坐标系(view space)中。
Direct3D 由 D3DXMatrixLookAtLH 函数计算得到。
4. 背面消隐
每个多边形都有两个侧面,其中一个侧面标记为正面(front side),另一个侧面标记为背面(back side)。通常多边形的背面是不可见的,这是由于场景中的多数物体都是封闭体。正面朝向的多边形称为正面朝向(front facing)多边形,正面偏离摄像机的多边形称为背面朝向(back facing)多边形。
正面朝向多边形遮挡了位于其后面的背面朝向多边形。 Direct3D 利用这一点将背面朝向的多边形加以剔除,这称为背面消隐。
为了实现背面消隐,Direct3D 需要区分哪些多边形是正面朝向的,哪些多边形是背面朝向的。默认状态下,Direct3D 认为顶点排列顺序为顺时针(观察坐标系中)的三角形单元是正面朝向的,顶点排列顺序是逆时针(观察坐标系中)的三角形单元式背面朝向的。
如果由于某些原因默认的消隐方式不能满足应用的要求,我们可通过修改绘制状态(render state) D3DRS_CULLMODE 来达到目的。
5. 光照
光源是在世界坐标系中定义的,但必须经过取景变换至观察坐标系方可使用。在观察坐标系中,光源照亮了场景中的物体,从而可以获得较为逼真的显示效果。
6. 裁剪
将位于视域体以外的几何体剔除掉,这个过程称为裁剪(clipping)。个人理解:类似于用人的眼睛看外界事物,有些物体可以完全被看见(我面前的显示器),有些物体完全看不见(我背后的门),有些物体可以看到一部分(我右边的床,我只能看到床头)。
7. 投影
在观察坐标系中,我们的任务是获取 3D 场景的 2D 表示。从 n 维变换为 n-1 维的过程称为投影。实现投影的方式有很多,我们只对其中一种感兴趣,即透视投影(perspective projection)。透视投影会产生“透视缩短”(foreshortenning)的视觉效果,即近大远小。
Direct3D 使用 D3DXMatrixPerspectiveFovLH 来创建一个投影矩阵。
8. 视口变换
视口变换(view port transform) 的任务是将顶点坐标从投影窗口转换到屏幕的一个矩形区域,该矩形区域称为视口(viewport)。个人理解:视口就是电脑桌面上的窗体而已。
Direct3D ,视口用结构 D3DVIEWPORT9 来表示。
9. 光栅化
顶点坐标变换为屏幕坐标后,我们就有了一个 2D 三角形单元的列表。光栅化(rasterization)的任务是为了绘制每个三角形单元,如何计算构成三角形单元的每个像素的颜色值。
光栅化过程的计算量非常大,我们应借助专用图形卡的加速功能。光栅化的最终结果是现实屏幕上的一幅 2D 图像。
/*******************************************************/
** 本文由 独酌逸醉 原创,转载请注明博客链接,谢谢!
** 小弟初学 Direct3D,文章中如果存在错误,烦请指证,不胜感激!
** 参考书籍:《DirectX 9.0 3D 游戏开发编程基础》
** 时间:2011.11.15
/*******************************************************/