D3D中多流的用法

2021-04-27 22:59:42 字數 4242 閱讀 5203

d3d中多流的用法

(本文為了方便起見,把directx graphics稱為d3d)

在d3d中,要渲染的頂點資料是放在vertex buffer中的,一般的做法是把頂點座標、顏色等按照自定義的頂點格式放在同乙個vertex buffer中,代表乙個流,然後通過fvf來告訴d3d要渲染的頂點的格式。但是在某些情況下,放在一起並不是最佳選擇。比如在動畫中,每一幀的頂點座標都在變化,但是紋理座標卻都不變(md3格式就是如此)。如果只用乙個流,每畫一幀就得把所有資料都拷貝到乙個臨時vertex buffer中再渲染,開銷巨大。如果能把不同的資料放在不同的流中,就可以只更新頂點座標的流,而紋理座標的流就可以保持不變了。而且,只用乙個vertex buffer時要管理fvf和資料結構體之間的關係,萬一弄錯了,是很難發現的。

如果使用多流,麻煩就能少些。下面就讓我們看看如何在d3d中實現多流。這個例子很簡單,顯示乙個三角形,三個頂點的顏色分別是紅、綠、藍。因為本例的資料只有頂點座標和顏色兩種資料,所以只有兩個vertex buffer。同時,由於d3d8在使用多流時必須使用shader來宣告頂點格式,所以宣告乙個g_shader變數。整個程式是這樣的:

#include

#include

#pragma comment(lib, "d3d8.lib")

#pragma comment(lib, "d3dx8.lib")

template

inline void safe_release(t& p)

}idirect3d8* g_pd3d = null;

idirect3ddevice8* g_pd3ddevice = null;

idirect3dvertexbuffer8* g_pvbpos = null;

idirect3dvertexbuffer8* g_pvbcol = null;

dword g_shader = 0xffffffff;

void initd3d(hwnd hwnd)

void initvb()

;// 位置資料

d3dvector positions =,,

,};// 顏色資料

d3dcolor colors =

;// 建立兩個vb

g_pd3ddevice->createvertexbuffer(3 * sizeof(d3dvector), d3dusage_dynamic | d3dusage_writeonly, 0, d3dpool_default, &g_pvbpos);

g_pd3ddevice->createvertexbuffer(3 * sizeof(d3dcolor), d3dusage_dynamic | d3dusage_writeonly, 0, d3dpool_default, &g_pvbcol);

// 建立vs

g_pd3ddevice->createvertexshader(shaderdecl, null, &g_shader, 0);

// 填充資料

void* ppositions;

g_pvbpos->lock(0, 0, reinterpret_cast(&ppositions), 0);

memcpy(ppositions, positions, sizeof(positions));

g_pvbpos->unlock();

void* pcolor;

g_pvbcol->lock(0, 0, reinterpret_cast(&pcolor), 0);

memcpy(pcolor, colors, sizeof(colors));

g_pvbcol->unlock();

}void cleanup()

void render()

lresult winapi msgproc(hwnd hwnd, uint msg, wparam wparam, lparam lparam)

return defwindowproc(hwnd, msg, wparam, lparam);

}lpctstr wcname(text("multistream"));

int winapi winmain(hinstance hinst, hinstance, lpstr, int)

else

}cleanup();

unregisterclass(wcname, wc.hinstance);

return 0;

}這裡把頂點座標放在乙個vb中,而把顏色放在另乙個vb中,也終於看到了setstreamsource的第乙個引數不是0的情況:-)。由於使用了兩個流,所以設定了0號和1號流,分別為前面填充的頂點座標流和顏色流。然後建立vertex shaer。由於這裡只使用固定的pipeline,所以createvertexshader的第二引數為null。要注意的是,setvertexshader的引數是verter shader的控制代碼,而不是fvf。如果沒有createvertexshader,而想當然地直接把fvf的值作為引數傳給setvertexshader,則會出現結果未定義的情況。

dx9的情況

d3d9對流的部分作了不少改進,所以,我們要寫的**也得做一些更改。全域性變數改為:

idirect3d9* g_pd3d = null;

idirect3ddevice9* g_pd3ddevice = null;

idirect3dvertexbuffer9* g_pvbpos = null;

idirect3dvertexbuffer9* g_pvbcol = null;

idirect3dvertexdeclaration9* g_pvertexdeclaration = null;

前四個變數不用說了,只是把8變成9。而idirect3dvertexdeclaration9是d3d9新增的,專門用於宣告流的格式,相當於乙個功能更強大的fvf。這回不用宣告vertex shader了。

initd3d中只需把

g_pd3d = direct3dcreate8(d3d_sdk_version);

改為g_pd3d = direct3dcreate9(d3d_sdk_version);

就行了。

initvb改為:

void initvb(),,

,};d3dvector positions =,,

,};d3dcolor colors =

;g_pd3ddevice->createvertexbuffer(3 * sizeof(d3dvector), d3dusage_dynamic | d3dusage_writeonly, 0, d3dpool_default, &g_pvbpos, null);

g_pd3ddevice->createvertexbuffer(3 * sizeof(d3dcolor), d3dusage_dynamic | d3dusage_writeonly, 0, d3dpool_default, &g_pvbcol, null);

g_pd3ddevice->createvertexdeclaration(shaderdecl, &g_pvertexdeclaration);

void* ppositions;

g_pvbpos->lock(0, 0, &ppositions, 0);

memcpy(ppositions, positions, sizeof(positions));

g_pvbpos->unlock();

void* pcolor;

g_pvbcol->lock(0, 0, &pcolor, 0);

memcpy(pcolor, colors, sizeof(colors));

g_pvbcol->unlock();

}在dx9中應該通過d3dvertexelement9來宣告資料格式,所以shaderdecl部分做了變化,並用createvertexdeclaration建立了乙個vertexdeclaration。

最後在render中把

g_pd3ddevice->setvertexshader(g_shader);

換成g_pd3ddevice->setvertexdeclaration(g_pvertexdeclaration);

這就是多流的dx9版本。

總結

靈活運用多流,能提高渲染效率,減少出錯的可能性。如果要做跨api的渲染系統,應該優先考慮使用多流。

參考

dx sdk

ogre

D3D中的渲染

虛擬世界中渲染幾何體一般來說有三種途徑 自定義座標渲染 d3dx內建模型渲染和外部模型資料渲染。第一步 定義頂點資料結構體 d3d提供了自定義頂點結構的機制,通過自定乙個結構體,來儲存我們所希望具有的頂點資料,例如 stuct colorvertex 頂點結構體定義好之後,需要用靈活頂點格式標記的組...

關於D3D中的顏色

1.當模型自帶顏色時,使用白色光照即可顯示出模型的本色,如果禁用光照,那麼模型就是黑色 2.當模型自帶顏色時,要通過設定material來設定模型的顏色,然後用白色光照之即可 1for dword i 0 i m dwnummtrls i 213m pmesh drawsubset i 14 15 ...

關於D3D中的顏色

1.當模型自帶顏色時,使用白色光照即可顯示出模型的本色,如果禁用光照,那麼模型就是黑色 2.當模型自帶顏色時,要通過設定material來設定模型的顏色,然後用白色光照之即可 3.有紋理的模型,一般不需要光照,因為紋理本身有顏色 4.每個模型繪製前要做好光照設定,比如禁用光照,或者指定某種顏色的光照...