Assembly-Language shader:硬件汇编着色程序.
推荐读物:Microsoft® DirectX® 9 Programmable Graphics Pipeline
“好记性不如烂笔头,留给自己~方便他人!!” -- Baesky
使用汇编着色器的步骤为:
1.声明一个字符串形式的着色代码;
2.汇编该着色代码;
3.获得shader对象;
4.声明物体顶点;
5.填充顶点缓冲;
6.创建顶点结构声明对象;
7.设置渲染状态;
8.设置其他相关变量与变换矩阵。
----------------------------------------------------------------------------------------
★声明字符串形式的着色代码
const char* strVertexShader =
"vs_1_1 \n"
"dcl_position v0 \n"
"m4x4 v0, c0 \n"
";\n"
"";
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
★汇编该着色代码
LPD3DXBUFFER pShader = NULL;
hr = D3DXAssembleShader(
strVertexShader,
(UINT)strlen(strVertexShader),
NULL,
NULL,
D3DXSHADER_DEBUG,
&pShader,
NULL
);
if (FAILED(hr))
{
SAFE_RELEASE(pShader);
return hr;
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
★获得shader对象
d3dDevice->CreateVertexShader(
(DWORD*)pShader->GetBufferPoint(), &vsObj);
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
★声明物体顶点 & 填充顶点缓冲
struct CUSTOMVETEX
{
float x,y,z;
}
CUSTOMVETEX vertices[] =
{
{0,1,1},
{1,0,1},
{-1,0,1},
}
d3dDevice->CreateVertexBuffer(
3*sizeof(CUSTOMVETEX), 0, 0, D3DPOOL_DEFAULT,
&p_vb, NULL);
VOID* pVertex;
p_vb->Lock(0, sizeof(vertices), (VOID**)&pVertex, 0);
memcpy(pVertex, vertices, sizeof(vertices));
p_vb->Unlock();
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
★创建顶点结构声明对象
D3DVERTEXELEMENT9 decl[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_POSITION, 0},
D3DDECL_END()
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
设置渲染状态与相关参数略。
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
下面是源代码:
#include <d3d9.h> #include <D3Dx9Shader.h> #define SAFE_RELEASE(p) { if ( (p) ) { (p)->Release(); (p) = 0; } } LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pD3dDevice = NULL; LPDIRECT3DVERTEXSHADER9 m_pAsm_VS; LPDIRECT3DVERTEXDECLARATION9 m_pVetexDel; D3DXMATRIX m_matWorld, m_matProj, m_matView; LPDIRECT3DVERTEXBUFFER9 vb; D3DXVECTOR3* eye; D3DXVECTOR3* at = new D3DXVECTOR3(0,0,0); D3DXVECTOR3* up = new D3DXVECTOR3(0,1,0); struct CUSTOMVERTEX { float x,y,z; }; HRESULT InitShader() { const char* strAssemblyShader = "vs_1_1 //version \n" "dcl_position v0 //define \n" "m4x4 oPos, v0, c0 //transform \n" ";\n" ""; LPD3DXBUFFER pShader = NULL; HRESULT hr = D3DXAssembleShader(strAssemblyShader, (UINT)strlen(strAssemblyShader), NULL,NULL,D3DXSHADER_DEBUG, &pShader, NULL); if(FAILED(hr)) { SAFE_RELEASE(pShader); return hr; } hr = g_pD3dDevice->CreateVertexShader((DWORD*)pShader->GetBufferPointer(), &m_pAsm_VS); if (FAILED(hr)) { SAFE_RELEASE(pShader); SAFE_RELEASE(m_pAsm_VS); return hr; } SAFE_RELEASE(pShader); CUSTOMVERTEX vertices[] = { {1,0,1}, {0,1,1}, {-1, 0,1}, }; if (FAILED(hr = g_pD3dDevice->CreateVertexBuffer(3*sizeof(CUSTOMVERTEX), 0, 0, D3DPOOL_DEFAULT, &vb, NULL))) { SAFE_RELEASE(vb); return hr; } VOID* pVertex; if (FAILED(hr = vb->Lock(0, sizeof(vertices), (VOID**)&pVertex, 0))) { return hr; } memcpy(pVertex, vertices, sizeof(vertices)); vb->Unlock(); D3DVERTEXELEMENT9 decl[] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, D3DDECL_END() }; if (FAILED(hr = g_pD3dDevice->CreateVertexDeclaration(decl, &m_pVetexDel))) { SAFE_RELEASE(m_pVetexDel); return hr; } g_pD3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); D3DXMatrixIdentity(&m_matWorld); D3DXMatrixPerspectiveFovLH(&m_matProj, D3DX_PI/4, 1.0f, 0.1f, 100.0f); return S_OK; } HRESULT InitD3D(HWND hWnd) { if ( (g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL ) { return E_FAIL; } D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3dDevice))) { return E_FAIL; } if (FAILED(InitShader())) { return E_FAIL; } return S_OK; } VOID CleanUp() { if (g_pD3D) { g_pD3D->Release(); g_pD3D = NULL; } if (g_pD3dDevice) { g_pD3dDevice->Release(); g_pD3dDevice = NULL; } } VOID Render() { if (NULL==g_pD3dDevice) return; eye = new D3DXVECTOR3(0,0,-3); D3DXMatrixLookAtLH(&m_matView, eye,at, up); g_pD3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(128,128,180), 1.0f, 0); if (SUCCEEDED(g_pD3dDevice->BeginScene())) { //TODO:render scene if (vb) { D3DXMATRIX mat; D3DXMatrixMultiply(&mat, &m_matWorld, &m_matView); D3DXMatrixMultiply(&mat, &mat, &m_matProj); D3DXMatrixTranspose(&mat, &mat); g_pD3dDevice->SetVertexShaderConstantF(0, (float*)&mat, 4); g_pD3dDevice->SetVertexDeclaration(m_pVetexDel); g_pD3dDevice->SetVertexShader(m_pAsm_VS); g_pD3dDevice->SetStreamSource(0, vb, 0, sizeof(CUSTOMVERTEX)); g_pD3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,1); g_pD3dDevice->SetVertexShader(NULL); } 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; } break; } return DefWindowProc(hWnd, msg, wParam, lParam); } INT WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR cmdLine, int ShowCmd) { WNDCLASSEX wc = { sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L, GetModuleHandle( NULL ), NULL, NULL, NULL, NULL, L"baesky", NULL }; RegisterClassEx( &wc ); // Create the application's window HWND hWnd = CreateWindow( L"baesky", L"我写的很乱 >_<", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, wc.hInstance, NULL ); if (SUCCEEDED(InitD3D(hWnd))) { ShowWindow(hWnd, SW_SHOWDEFAULT); UpdateWindow(hWnd); // Enter the message loop MSG msg; ZeroMemory( &msg, sizeof( msg ) ); while( msg.message != WM_QUIT ) { if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else Render(); } } CleanUp(); UnregisterClass(L"baesky", hInstance); return 0; }