请教有关DX中多流的问题
这是网上一篇文档中的例子,这里拿来show一下,希望原作者见谅:
其中在函数InitVB中函数
g_pd3dDevice->CreateVertexDeclaration(shaderDecl, &g_pVertexDeclaration);
调用失败,如果把
{ 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT,D3DDECLUSAGE_POSITIONT, 0 },改成{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },就正确,这里不知道为什么使用XYZRHW的顶点格式在创建VertexDeclaration的时候会失败???
源代码如下:
//////////////////////////////
#include <d3d9.h>
#include <d3dx9.h>
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
template <typename T>
inline void SAFE_RELEASE(T& p)
{
if (p != 0)
{
p->Release();
p = 0;
}
}
IDirect3D9* g_pD3D = NULL;
IDirect3DDevice9* g_pd3dDevice = NULL;
IDirect3DVertexBuffer9* g_pVBPos = NULL;
IDirect3DVertexBuffer9* g_pVBCol = NULL;
IDirect3DVertexDeclaration9* g_pVertexDeclaration = NULL;
void InitD3D(HWND hWnd)
{
g_pD3D = Direct3DCreate9(D3D_SDK_VERSION);
D3DDISPLAYMODE d3ddm;
g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = d3ddm.Format;
g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice);
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
D3DXMATRIX matWorld;
D3DXMatrixIdentity(&matWorld);
g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);
D3DXMATRIX matView;
D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0, 0, -3), &D3DXVECTOR3(0, 0, 0), &D3DXVECTOR3(0, 1, 0));
g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);
D3DXMATRIX matProj;
D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4, 1, 0.1f, 10);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
}
void InitVB()
{
D3DVERTEXELEMENT9 shaderDecl[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT, 0 },
{ 1, 0, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
{ 0xFF, 0, D3DDECLTYPE_UNUSED, 0, 0, 0 },
};
g_pd3dDevice->CreateVertexDeclaration(shaderDecl, &g_pVertexDeclaration);
D3DXVECTOR4 Positions[] =
{
D3DXVECTOR4( 100, 100, 1.0f, 1.0f ),
D3DXVECTOR4( 200, 100, 1.0f, 1.0f ),
D3DXVECTOR4( 100, 200, 1.0f, 1.0f ),
};
D3DCOLOR Colors[] =
{
D3DCOLOR_XRGB(0xFF, 0, 0),
D3DCOLOR_XRGB(0, 0xFF, 0),
D3DCOLOR_XRGB(0, 0, 0xFF),
};
g_pd3dDevice->CreateVertexBuffer(3 * sizeof(D3DXVECTOR4), 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);
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();
}
void Cleanup()
{
// 释放两个流
g_pd3dDevice->SetStreamSource( 0, NULL, 0, sizeof(D3DXVECTOR4));
g_pd3dDevice->SetStreamSource( 1, NULL, 0, sizeof(D3DCOLOR));
// 删除VS
g_pVertexDeclaration->Release();
SAFE_RELEASE(g_pVBPos);
SAFE_RELEASE(g_pVBCol);
SAFE_RELEASE(g_pd3dDevice);
SAFE_RELEASE(g_pD3D);
}
void Render()
{
g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0x33, 0x66, 0x99), 1.0f, 0);
g_pd3dDevice->BeginScene();
HRESULT hr;
hr = g_pd3dDevice->SetVertexDeclaration(g_pVertexDeclaration);
hr = g_pd3dDevice->SetStreamSource( 0, g_pVBPos, 0, sizeof(D3DXVECTOR4));
hr = g_pd3dDevice->SetStreamSource( 1, g_pVBCol, 0, sizeof(D3DCOLOR));
hr = g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );
g_pd3dDevice->EndScene();
g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}
LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
LPCTSTR wcName(TEXT("Multistream"));
INT WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, INT)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MsgProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = static_cast<HBRUSH>(GetStockObject(BLACK_BRUSH));
wc.lpszMenuName = NULL;
wc.lpszClassName = wcName;
RegisterClass(&wc);
HWND hWnd(CreateWindow(wcName, wcName, WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, GetDesktopWindow(), NULL, wc.hInstance, NULL));
InitD3D(hWnd);
InitVB();
ShowWindow(hWnd, SW_SHOWDEFAULT);
UpdateWindow(hWnd);
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
Render();
}
}
Cleanup();
UnregisterClass(wcName, wc.hInstance);
return 0;
}
////////////////////////////
以下是摘自dx help文档有关D3DDECLUSAGE_POSITIONT的说明,不知道我的code中错在哪儿?:
Vertex Declarations with D3DDECLUSAGE_POSITIONT
Presence of a vertex element with (D3DUSAGE_POSITIONT, 0) is used to indicate to the device that the vertex data coming in has already been through vertex processing (like an FVF with D3DFVF_XYZRHW bit set). At Draw time, if the currently set declaration has an element with the (D3DUSAGE_POSITIONT, 0) semantic, the entire vertex processing is skipped (just as if an FVF with D3DFVF_XYZRHW bit has been set).
There are some restrictions on vertex declarations with (D3DDECLUSAGE_POSITIONT, 0):
Only stream zero can be used is such declarations.
Vertex elements must be sorted by increasing stream offset.
Stream offset must be DWORD aligned.
The same (Usage, Usage Index) pair should be listed only once.
Only D3DDECLMETHOD_DEFAULT method can be used.
Other vertex elements cannot have (D3DDECLUSAGE_POSITION, 0) semantic.
In addition, there are some restrictions on such declaration, related to the device driver version. These restrictions are in effect because Direct3D sends such declarations directly to the driver without doing any conversion.