1.D3D 從0到一個圖元的繪製 的步驟
(1).初始化D3D(LPDIRECT3D9)和Device(LPDIRECT3DDEVICE9)對象。
這裡的主要作用是:設定back buffer的個數、格式,還有在swapBuffer之後對buffer的處理方法,比如back buffer的內容被刪除或者back buffer的內容部變;是否啟用 z-buffer 或者 模板緩衝 和 這兩個緩衝的格式; 全屏渲染和消除鋸齒效果等。
(2).準備頂點資料:讓VB(vertex buffer)和Device關聯起來,並把已知的一組資料寫入到VB裡面
(3).清除back buffer的當前緩衝器(也可以有深度緩衝器、模板緩衝),設定世界矩陣、投影矩陣和視點
(4).設定device的當前VB,並且設定這個VB的格式,然後繪製圖元
(5).程式結束,釋放資源。
其中(1)、(3)、(5)的內容可以在 <<從0到第一個D3D程式>> 裡面找到
2.對第(2)步準備資料的說明
(1)頂點緩衝的概念和建立的方法
頂點緩衝是一片連續的記憶體空間,是由D3D分配和管理的,是用來儲存頂點資料的。
頂點資料的內容可以包含頂點的(x,y,z)座標資料、頂點的顏色資料(diffuse)、紋理座標資料等等。
頂點緩衝和D3D對象一樣,也是一個對象: LPDIRECT3DVERTEXBUFFER9, 它也是由D3D進行管理的。
在device裡面給一個 VB 對象分配記憶體和設定這個VB對象屬性的方法是:
HRESULT IDirect3DDevice9::CreateVertexBuffer(
UINT Length,
DWORD Usage,
DWORD FVF,
D3DPOOL Pool,
IDirect3DVertexBuffer9** ppVertexBuffer,
HANDLE* pSharedHandle
);
Length —— 分配給緩衝的位元組大小。假如想得到一個能儲存8個頂點的頂點緩衝,那麼我們就要在頂點結構中設定這個參數為 8 * sizeof ( Vertex ) 。
Usage —— 指定關於怎樣使用緩衝的額外資訊。這個值可以是0,沒有標記,或者是下面標記的一個或多個的組合:
D3DUSAGE_DYNAMIC——設定這個參數可以使緩衝是動態。
D3DUSAGE_POINTS——這個參數指定緩衝儲存原始點。這個參數僅僅用在頂點緩衝中。
D3DUSAGE_SOFTWAREPROCESSING——使用軟體頂點處理
D3DUSAGE_WRITEONLY——指定應用程式只能寫緩衝。它允許驅動程式分配最適合的記憶體位址作為寫緩衝。注意如果從建立好的這種緩衝中讀資料,將會返回錯誤資訊。
FVF —— 儲存在緩衝中的頂點格式。
頂點緩衝的資料格式及其值的type的對應關係見:http://www.cnblogs.com/xmzyl/articles/1604096.html
Pool —— 緩衝放置在哪一個記憶體池中.我們採用的是D3DPOOL_DEFAULT,意思是頂點緩衝區儘可能存在顯存中。
ppVertexBuffer ——返回建立好的頂點緩衝的指標。
pSharedHandle ——沒有使用;設定為0。
注意:不使用D3DUSAGE_DYNAMIC參數建立的緩衝被叫做靜態緩衝。靜態緩衝通常被放置在顯存中,在其中的資料能被很有效處理。然而,對於靜態緩衝,從中讀取和寫入資料是很慢的,因為訪問顯存是很慢的。因為這個原因我們用靜態緩衝儲存待用資料(不需要被經常改變的資料)。地形和建築物是很好的候選例子,因為在應用程式中他們通常不需要被改變。靜態緩衝應該在應用程式初始化的時候就被填充好,而不是在運行時才做。
注意:使用D3DUSAGE_DYNAMIC參數建立的緩衝被叫做動態緩衝。動態緩衝通常被放在AGP記憶體中,這種記憶體中的資料能被很快的更新。處理動態緩衝中的資料不會比處理靜態緩衝中的資料快,因為這些資料必須在渲染前被轉移到顯存中,動態緩衝的好處是它們能夠被稍微快點地被更新(比CPU寫快)。因此,假如你需要經常更新緩衝中的資料,那麼你就應該使用動態緩衝。粒子系統是很好的一個應用,因為它們是動態,並且他們通常每一幀都會被更新。
注意:在程式中讀取顯存和AGP記憶體都是非常慢的。因此,假如你在運行時需要讀取你的幾何物體,最好的方案是指定一塊系統記憶體,往其中拷貝並且讀取資料。
(2)頂點緩衝的讀和寫
我們通過得到一個頂點緩衝的記憶體指標來讀寫緩衝中的資料,方法是lock:
HRESULT IDirect3DVertexBuffer9::Lock(
UINT OffsetToLock,
UINT SizeToLock,
BYTE** ppbData,
DWORD Flags
);
OffsetToLock —— 位移量,以位元組為單位,從緩衝開始位置到鎖定開始位置的距離。
SizeToLock —— 鎖定的位元組數。
ppbData —— 一個指向鎖定記憶體開始位置的指標。
Flags —— 標記描述怎樣鎖定記憶體。它可能是0或者是下面參數中的1個或多個的組合:
D3DLOCK_DISCARD——這個參數僅僅會在動態緩衝時被使用。它指示硬體丟棄緩衝並返回一個指向新分配的緩衝的指標。這是很有用,因為當我們存取一個新分配的緩衝時它允許硬體繼續從丟棄的緩衝渲染。這防止了硬體延遲。
D3DLOCK_NOOVERWRITE——這個參數僅僅會在動態緩衝時被使用。它聲明你將向緩衝中添加資料。即你不能向已經渲染的記憶體中寫資料。這是有好處的因為他允許你在添加新資料到緩衝的同時讓硬體繼續渲染。
D3DLOCK_READONLY——這個參數聲明你鎖定的緩衝只能從中讀取資料而不能寫資料。這允許一些內在的最佳化。
用參數D3DLOCK_DISCARD和D3DLOCK_NOOVERWRITE表明緩衝的一部分被鎖定之後能繼續被使用。假如硬體設定允許這些標記被使用,則在對緩衝進行鎖定時,其他的顯示操作就不會中斷。
下邊的例子展示了通常怎樣使用Lock方法。注意當我們使用完以後要調用Unlock方法。
Vertex* vertices;
_vb->Lock(0, 0, (void**)&vertices, 0); // 鎖定整個緩衝
vertices[0] = Vertex(-1.0f, 0.0f, 2.0f); // 向緩衝裡寫頂點
vertices[1] = Vertex( 0.0f, 1.0f, 2.0f);
vertices[2] = Vertex( 1.0f, 0.0f, 2.0f);
_vb->Unlock(); // 當你訪問完緩衝時,解鎖緩衝
3.對第(4)步的說明
設定device的當前VB,並且設定這個VB的格式,然後繪製圖元。
步驟:
m_pDevice->SetStreamSource(0,m_pVB,0,sizeof CUSTOMVERTEX);
m_pDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
m_pDevice->DrawPrimitive(D3DPT_LINELIST,0,3);//這裡的圖元類型是 D3DPT_LINELIST,是一些線段。
//圖元相關可以參見:http://blog.csdn.net/niyongfu14/article/details/6617977
HRESULT SetStreamSource(
UINT StreamNumber, //渲染資料流序號,資料流的概念會在紋理相關處理時遇到,現在就為0
IDirect3DVertexBuffer9 *pStreamData, //進行綁定的頂點緩衝區指標
UINT OffsetInBytes, //進行綁定串連的渲染資料流的起始位置
UINT Stride //渲染資料流中一個頂點所佔的記憶體的大小
);