DIRECTX9.0繪製流水線
主要目的是:
在給定的3D場景和指定觀察方向的虛擬攝像機(virtual camera)的幾何描述時,創建一幅2D圖像
一.模型表示:
三角形網格是構建物體模型的基本單元.
1.頂點格式:
頂點除了包含空間信息外,還可以包含其他的附加屬性
頂點格式可以自己進行定義,這樣的靈活頂點格式(Flexible vertexFormat, FVF)可用D3DFVF來進行描述我們自己定義的頂點格式.
例如:
#define FVF_NORMAL_TEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
struct NormalTexVertex
{
float _x, _y, _z;
float _nx, _ny, _nz;
float _u, _v;
}
以上定義的含義是對應於該頂點格式的頂點結構,包含了位置,法線以及紋理座標等屬性.
定義靈活頂點格式時必須遵循的一個約定是:靈活頂點格式標記的指定順序必須與頂點結構中相應類型數據定義的順序保持一致.
2.三角形單元
三角形單元是3D物體的基本組成部分
繞序(winding order)
順時針爲正面
3.索引
構成一個3d物休的衆多三角形單元之間會共享許多公共頂點,爲解決該問題引入了索引(indices).
我們創建一個頂點列表(vertex list)和一個索引列表(index list).
頂點列表包含了全部獨立頂點,索引列表包含了指向頂點列表的索引,這些索引規定了爲構建三角形單元,各頂點應按何種方式來組織.
二.虛擬攝像機:
攝像機指定了場景對觀察者的可見部分,即我們將依據哪部分3D場景來創建2D圖像.在世界座標系中,攝像機有一定的位置和方向,定義了可見的空間體積(volume of space).
攝像機的視角空間是一個平截頭體(frustum),在3d圖形學中也可稱爲視域體或視截體.
投影窗口(projection window)是一個2D區域,是由3d幾何體通過投影映射而得.很重要的一點是,矩形投影窗口在x和y方向座標的最小值是min=(-1, -1),最大值是max=(1,1)
爲簡化繪製工作,我們將近裁剪面和投影平面合二爲一.注意,direct3d將投影平面定義爲平面z=1;
三.繪製流水線:
應用一個變換矩陣的方法是使用IDirect3DDevice9->SetTransform方法
1.局部座標系
局部座標系local space或建模座標系modeling space是用於定義構成物體的三解形單元列表的座標系.
2.世界座標系
構建各種物體模型時,每個模型都位於其自身的局部座標系中.我們還需要將這些物體組織在一起構成世界座標系(全局座標系)中的場景.位於局部座標系中的物體通過一個稱爲世界變換world transform 的運算變換到世界座標系中,該變換通常包括平衡,旋轉以及比例運算,分別用於設定該物體在世界座標系中的位置,方向以及模型的大小.
世界變換用一個矩陣來表示:
Device->SetTransform(D3DTS_WORLD, 變換矩陣)
3.觀察座標系
攝像機放在原點,讓光軸與世界座標系z軸正方向一致,同時,世界空間中的所有幾何體都有隨着攝像機一同進行變換,以保證攝像機的視場恆定.這種變換稱爲取景變換view space transformation, 我們稱變換後的幾何體位於觀察座標系view space 中
取景變換矩陣可由
//建立一個左手觀察座標系
D3DXMATRIX * D3DXMatrixLookAtLH(
D3DXMATRIX *pOut,
CONST D3DXVECTOR3 *pEye, //攝像機在世界座標系中的位置
CONST D3DXVECTOR3 *pAt, //指定世界座標系中被觀察點
CONST D3DXVECTOR3 *pUp //向上的方向向量
);
例:
D3DXVECTOR3 position(5.0f, 3.0f, –10.0f);
D3DXVECTOR3 targetPoint(0.0f, 0.0f, 0.0f);
D3DXVECTOR3 worldUp(0.0f, 1.0f, 0.0f);
D3DXMATRIX V;
D3DXMatrixLookAtLH(&V, &position, &targetPoint, &worldUp);
Device->SetTarnsform(D3DTS_VIEW, &v); //取景變換需要用此方法來設定
4.背面消隱
每個多邊形都有兩個側面,我們將其中一個側面標記爲正面,另一個側面標記爲背面,正面朝向多邊形評功遮擋了位於其背面朝向的多邊形,Direct3D正是利用了這一點而將背面朝向多邊形加以剔除,這稱爲消隱
爲了實現背面消隱,Direct3D需要區分哪能引動多邊形是下面朝向的,哪些是朝向的,聊勝於無狀態下.Direct3D認爲頂點排列順序爲順時針的三角形單元是下面朝向的,頂點排列順序爲逆時針的三角形單元是背面朝向的.
如果由於某些原因的消隱方式不能滿足應用的要求,我們可以通過修改繪製狀態來達到目的.
HRESULT SetRenderState(
D3DRENDERSTATETYPE State, //要改變的參數
DWORD Value //改變的值
);
State=D3DRS_CULLMODE
VALUE:
D3DCULL_NONE 完全禁用背面消隱。
D3DCULL_CW 只對順時針繞序的三角形單元進行消隱。
D3DCULL_CCW 默認值,只對逆時針繞序的三角形單元進行消隱。
5.光照
光源是在世界座標系中定義的,但必須經取景變換至觀察座標系方可使用.
6.裁剪
現在我們想將那些位於視域體外的幾何體剔除掉,這個過程稱爲裁剪.
7.投影:
觀察座標系中,我們的任務是獲取3D場景的2D表示,從n維變換爲n-1維的過程稱爲投影projection.
我們只處理透視投影perspective projection透視投影會產生"透視縮短"foreshortening的視覺效果,即近大遠小這類投影使得我們可以用2D圖像表示3D場景.
投影變換定義了視域體,並負責將視域體中的幾何體投影到投影窗口中
//依據視域體的描述信息創建一個投影矩陣
D3DXMATRIX * D3DXMatrixPerspectiveFovLH(
D3DXMATRIX *pOut,
FLOAT fovy, //角度
FLOAT Aspect, //長高比
FLOAT zn, //到最近平面的距離
FLOAT zf //到最遠平面的距離
);
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(&proj, PI * 0.5f, (float)width/(float)height, 1.0f, 1000.0f);
Device->SetTransform(D3DTS_PROJECTION. &proj);
8.視口變換
視口變換viewport transform的任務是將頂點座標從投影窗口轉換到屏幕的一個矩形區域中,該矩形區域稱爲視口viewport.
矩形的視口是相對於窗口來描述的,因爲禍患總是處於窗口內部並且其位置要用窗口座標來指定
typedef struct D3DVIEWPORT9 {
DWORD X;
DWORD Y;
DWORD Width;
DWORD Height; //前4個數據成員定義了視口矩形相對對於其父窗口的位置及大小
float MinZ; //深度緩存中的最小深度值
float MaxZ; //最大深度值[0,1]
} D3DVIEWPORT9, *LPD3DVIEWPORT9;
一旦我們填充好D3DVIEWPORT9結構,就可這樣來設置視口:
D3DVIEWPORT9 vp = {0, 0, 640, 480, 0, 1};
Device->SetViewport(& vp);
9.光柵化:
爲了繪製每個三角形單元,如何計算構成三角形單元的每個像素的顏色值