在DirectX程序中我们可以使用 D3DPT_POINTLIST, D3DPT_LINELIST, D3DPT_LINESTRIP, D3DPT_TRIANGLELIST, D3DPT_TRIANGLESTRIP, D3DPT_TRIANGLEFAN 几种图元类型绘制顶点。
我们先看以下使用这几种绘制图元类型的代码:
//******************************************************************** // Filename: Main.cpp // Author: Chinafish // Modifier: Chinafish // Created: 2010-06-25 16:13 // Updated: 2010-06-25 16:13 // QQ: 149200849 // MSN: china_fish@msn.com // Purpose: Primitive types. //==================================================================== // Copyright(C) 2004-2010 by Chinafish. All Rights Reserved. //******************************************************************** #define STRICT #define WIN32_LEAN_AND_MEAN #include "windows.h" // Link D3D #include "d3d9.h" #include "d3dx9.h" #pragma comment(lib, "d3d9.lib") #pragma comment(lib, "d3dx9.lib") #define Release_Safe(p){if(p!=NULL) p->Release();} #define WINDOW_TITLE "www.csinx.org - Primitive Types (DX9+VC7)" #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 //----------------------------------------------------------------------------- // GLOBALS //----------------------------------------------------------------------------- HWND g_hWnd = NULL; LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; D3DPRESENT_PARAMETERS g_d3dpp; LPDIRECT3DVERTEXBUFFER9 g_pPointList_VB = NULL; LPDIRECT3DVERTEXBUFFER9 g_pLineStrip_VB = NULL; LPDIRECT3DVERTEXBUFFER9 g_pLineList_VB = NULL; LPDIRECT3DVERTEXBUFFER9 g_pTriangleList_VB = NULL; LPDIRECT3DVERTEXBUFFER9 g_pTriangleStrip_VB = NULL; LPDIRECT3DVERTEXBUFFER9 g_pTriangleFan_VB = NULL; #define D3DFVF_MY_VERTEX ( D3DFVF_XYZ | D3DFVF_DIFFUSE ) struct Vertex { float x, y, z; // Position of vertex in 3D space DWORD color; // Color of vertex }; bool g_bRenderInWireFrame = false; // // We'll store the vertex data in simple arrays until we're ready to load // them into actual Direct3D Vertex Buffers. Seeing the vertices laid out // like this should make it easier to understand how vertices need to be // passed to be considered valid for each primitive type. // Vertex g_VertexData[] = { {-2.0f, 0.0f, 0.0f, D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 ) }, {-1.0f, 1.0f, 0.0f, D3DCOLOR_COLORVALUE( 0.0, 1.0, 0.0, 1.0 ) }, {-1.0f, 0.0f, 0.0f, D3DCOLOR_COLORVALUE( 0.0, 0.0, 1.0, 1.0 ) }, { 0.0f, 1.0f, 0.0f, D3DCOLOR_COLORVALUE( 1.0, 1.0, 0.0, 1.0 ) }, { 0.0f, 0.0f, 0.0f, D3DCOLOR_COLORVALUE( 0.0, 1.0, 1.0, 1.0 ) }, { 1.0f, 1.0f, 0.0f, D3DCOLOR_COLORVALUE( 1.0, 0.0, 1.0, 1.0 ) }, { 1.0f, 0.0f, 0.0f, D3DCOLOR_COLORVALUE( 1.0, 0.0, 0.0, 1.0 ) }, { 2.0f, 1.0f, 0.0f, D3DCOLOR_COLORVALUE( 0.0, 1.0, 0.0, 1.0 ) } }; DWORD g_dwBackBufferWidth = 0; DWORD g_dwBackBufferHeight = 0; //----------------------------------------------------------------------------- // PROTOTYPES //----------------------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow); LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void InitD3D(); void ShutDown(void); void Render(void); //----------------------------------------------------------------------------- // Name: WinMain() // Desc: The application's entry point //----------------------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX winClass; MSG uMsg; memset(&uMsg,0,sizeof(uMsg)); winClass.lpszClassName = "CLASS_PRIMITIVETYPES"; winClass.cbSize = sizeof(WNDCLASSEX); winClass.style = CS_HREDRAW | CS_VREDRAW; winClass.lpfnWndProc = WindowProc; winClass.hInstance = hInstance; winClass.hIcon = LoadIcon(hInstance, (LPCTSTR)NULL); winClass.hIconSm = LoadIcon(hInstance, (LPCTSTR)NULL); winClass.hCursor = LoadCursor(NULL, IDC_ARROW); winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); winClass.lpszMenuName = NULL; winClass.cbClsExtra = 0; winClass.cbWndExtra = 0; if(!RegisterClassEx(&winClass)) return E_FAIL; g_hWnd = CreateWindowEx(NULL, "CLASS_PRIMITIVETYPES", WINDOW_TITLE, WS_EX_TOPMOST, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL); if(g_hWnd == NULL) return E_FAIL; // Adjust window RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT }; AdjustWindowRect(&rect, GetWindowLong(g_hWnd, GWL_STYLE), FALSE); SetWindowPos(g_hWnd, 0, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER | SWP_NOMOVE); ShowWindow(g_hWnd, nCmdShow); UpdateWindow(g_hWnd); // Init or reset D3D InitD3D(); while(uMsg.message != WM_QUIT) { if(PeekMessage(&uMsg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&uMsg); DispatchMessage(&uMsg); } else { // Render a frame Render(); } } ShutDown(); UnregisterClass("CLASS_PRIMITIVETYPES", winClass.hInstance); return uMsg.wParam; } //----------------------------------------------------------------------------- // Name: WindowProc() // Desc: The window's message handler //----------------------------------------------------------------------------- LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_KEYDOWN: { switch(wParam) { case VK_ESCAPE: PostQuitMessage(0); break; case 0x57: // W { g_bRenderInWireFrame = !g_bRenderInWireFrame; if( g_bRenderInWireFrame == true ) g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME ); else g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID ); } break; } } break; case WM_CLOSE: { PostQuitMessage(0); } case WM_DESTROY: { PostQuitMessage(0); } break; default: { return DefWindowProc(hWnd, msg, wParam, lParam); } break; } return 0; } //----------------------------------------------------------------------------- // Name: InitD3D() // Desc: This function will only be called once during the application's // initialization phase. Therefore, it can't contain any resources that // need to be restored every time the Direct3D device is lost or the // window is resized. //----------------------------------------------------------------------------- void InitD3D() { // Create D3D g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); if(!g_pD3D) { MessageBox(NULL, "Direct3DCreate9() - Failed!", "Error", NULL); return; } D3DDISPLAYMODE d3ddm; g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm); ZeroMemory(&g_d3dpp, sizeof(g_d3dpp)); g_d3dpp.Windowed = TRUE; g_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; g_d3dpp.BackBufferFormat = d3ddm.Format; g_d3dpp.EnableAutoDepthStencil = TRUE; g_d3dpp.AutoDepthStencilFormat = D3DFMT_D16; g_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, g_hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &g_d3dpp, &g_pd3dDevice); if(!g_pd3dDevice) { return; } // // Cache the width & height of the back-buffer... // LPDIRECT3DSURFACE9 pBackBuffer = NULL; D3DSURFACE_DESC d3dsd; g_pd3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer); pBackBuffer->GetDesc(&d3dsd); pBackBuffer->Release(); g_dwBackBufferWidth = d3dsd.Width; g_dwBackBufferHeight = d3dsd.Height; // Light and cullmode g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE); g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); D3DXMATRIX mProjection; D3DXMatrixPerspectiveFovLH( &mProjection, D3DXToRadian( 45.0f ), 1.0f, 1.0f, 100.0f ); g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &mProjection ); Vertex *pVertices = NULL; // // Point List // g_pd3dDevice->CreateVertexBuffer( 8*sizeof(Vertex), 0, D3DFVF_MY_VERTEX, D3DPOOL_DEFAULT, &g_pPointList_VB, NULL ); pVertices = NULL; g_pPointList_VB->Lock( 0, sizeof(g_VertexData), (void**)&pVertices, 0 ); memcpy( pVertices, g_VertexData, sizeof(g_VertexData) ); g_pPointList_VB->Unlock(); // // Line List // g_pd3dDevice->CreateVertexBuffer( 8*sizeof(Vertex), 0, D3DFVF_MY_VERTEX, D3DPOOL_DEFAULT, &g_pLineList_VB, NULL ); pVertices = NULL; g_pLineList_VB->Lock( 0, sizeof(g_VertexData), (void**)&pVertices, 0 ); memcpy( pVertices, g_VertexData, sizeof(g_VertexData) ); g_pLineList_VB->Unlock(); // // Line Strip // g_pd3dDevice->CreateVertexBuffer( 8*sizeof(Vertex), 0, D3DFVF_MY_VERTEX, D3DPOOL_DEFAULT, &g_pLineStrip_VB, NULL ); pVertices = NULL; g_pLineStrip_VB->Lock( 0, sizeof(g_VertexData), (void**)&pVertices, 0 ); memcpy( pVertices, g_VertexData, sizeof(g_VertexData) ); g_pLineStrip_VB->Unlock(); // // Triangle List // g_pd3dDevice->CreateVertexBuffer( 8*sizeof(Vertex), 0, D3DFVF_MY_VERTEX, D3DPOOL_DEFAULT, &g_pTriangleList_VB, NULL ); pVertices = NULL; g_pTriangleList_VB->Lock( 0, sizeof(g_VertexData), (void**)&pVertices, 0 ); memcpy( pVertices, g_VertexData, sizeof(g_VertexData) ); g_pTriangleList_VB->Unlock(); // // Triangle Strip // g_pd3dDevice->CreateVertexBuffer( 8*sizeof(Vertex), 0, D3DFVF_MY_VERTEX, D3DPOOL_DEFAULT, &g_pTriangleStrip_VB, NULL ); pVertices = NULL; g_pTriangleStrip_VB->Lock( 0, sizeof(g_VertexData), (void**)&pVertices, 0 ); memcpy( pVertices, g_VertexData, sizeof(g_VertexData) ); g_pTriangleStrip_VB->Unlock(); // // Triangle Fan // g_pd3dDevice->CreateVertexBuffer( 8*sizeof(Vertex), 0, D3DFVF_MY_VERTEX, D3DPOOL_DEFAULT, &g_pTriangleFan_VB, NULL ); pVertices = NULL; g_pTriangleFan_VB->Lock( 0, sizeof(g_VertexData), (void**)&pVertices, 0 ); memcpy( pVertices, g_VertexData, sizeof(g_VertexData) ); g_pTriangleFan_VB->Unlock(); } //----------------------------------------------------------------------------- // Name: ShutDown() // Desc: Release all //----------------------------------------------------------------------------- void ShutDown(void) { Release_Safe(g_pPointList_VB); Release_Safe(g_pLineList_VB); Release_Safe(g_pLineStrip_VB); Release_Safe(g_pTriangleList_VB); Release_Safe(g_pTriangleStrip_VB); Release_Safe(g_pTriangleFan_VB); Release_Safe(g_pd3dDevice); Release_Safe(g_pD3D); } //----------------------------------------------------------------------------- // Name: Render() // Desc: Render something you want //----------------------------------------------------------------------------- void Render(void) { D3DXMATRIX mWorld; D3DXMatrixTranslation( &mWorld, 0.0f, 0.0f, 10.0f ); g_pd3dDevice->SetTransform( D3DTS_WORLD, &mWorld ); int nNum = sizeof(g_VertexData)/sizeof(Vertex); ////////////////////////////////////////////////////////////////////////////////// D3DVIEWPORT9 vp1; vp1.X = 0; vp1.Y = 0; vp1.Width = (g_dwBackBufferWidth-20) / 3 + 10; vp1.Height = g_dwBackBufferHeight / 2; vp1.MinZ = 0.0f; vp1.MaxZ = 1.0f; g_pd3dDevice->SetViewport(&vp1); // Clear screen with D3DCOLOR_XRGB(0, 0, 0) g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); g_pd3dDevice->BeginScene(); // Render geometry here... g_pd3dDevice->SetStreamSource( 0, g_pPointList_VB, 0, sizeof(Vertex) ); g_pd3dDevice->SetFVF( D3DFVF_MY_VERTEX ); // D3DPT_POINTLIST // D3DPT_LINELIST // D3DPT_LINESTRIP // D3DPT_TRIANGLELIST // D3DPT_TRIANGLESTRIP // D3DPT_TRIANGLEFAN g_pd3dDevice->DrawPrimitive( D3DPT_POINTLIST, 0, nNum ); g_pd3dDevice->EndScene(); ////////////////////////////////////////////////////////////////////////////////// D3DVIEWPORT9 vp2; vp2.X = 10 + (g_dwBackBufferWidth-20) / 3; vp2.Y = 0; vp2.Width = (g_dwBackBufferWidth-20) / 3; vp2.Height = g_dwBackBufferHeight / 2; vp2.MinZ = 0.0f; vp2.MaxZ = 1.0f; g_pd3dDevice->SetViewport( &vp2 ); // Clear screen with D3DCOLOR_XRGB(0, 0, 0) g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); g_pd3dDevice->BeginScene(); // Render geometry here... g_pd3dDevice->SetStreamSource( 0, g_pLineList_VB, 0, sizeof(Vertex) ); g_pd3dDevice->SetFVF( D3DFVF_MY_VERTEX ); // D3DPT_POINTLIST // D3DPT_LINELIST // D3DPT_LINESTRIP // D3DPT_TRIANGLELIST // D3DPT_TRIANGLESTRIP // D3DPT_TRIANGLEFAN g_pd3dDevice->DrawPrimitive( D3DPT_LINELIST, 0, nNum / 2); g_pd3dDevice->EndScene(); ////////////////////////////////////////////////////////////////////////////////// D3DVIEWPORT9 vp3; vp3.X = 10 + ((g_dwBackBufferWidth-20) / 3) * 2; vp3.Y = 0; vp3.Width = (g_dwBackBufferWidth-20) / 3 + 10; vp3.Height = g_dwBackBufferHeight / 2; vp3.MinZ = 0.0f; vp3.MaxZ = 1.0f; g_pd3dDevice->SetViewport(&vp3); // Clear screen with D3DCOLOR_XRGB(0, 0, 0) g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); g_pd3dDevice->BeginScene(); // Render geometry here... g_pd3dDevice->SetStreamSource( 0, g_pLineStrip_VB, 0, sizeof(Vertex) ); g_pd3dDevice->SetFVF( D3DFVF_MY_VERTEX ); // D3DPT_POINTLIST // D3DPT_LINELIST // D3DPT_LINESTRIP // D3DPT_TRIANGLELIST // D3DPT_TRIANGLESTRIP // D3DPT_TRIANGLEFAN g_pd3dDevice->DrawPrimitive( D3DPT_LINESTRIP, 0, nNum - 1); g_pd3dDevice->EndScene(); ////////////////////////////////////////////////////////////////////////////////// D3DVIEWPORT9 vp4; vp4.X = 0; vp4.Y = g_dwBackBufferHeight / 2; vp4.Width = (g_dwBackBufferWidth-20) / 3 + 10; vp4.Height = g_dwBackBufferHeight / 2; vp4.MinZ = 0.0f; vp4.MaxZ = 1.0f; g_pd3dDevice->SetViewport(&vp4); // Clear screen with D3DCOLOR_XRGB(0, 0, 0) g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); g_pd3dDevice->BeginScene(); // Render geometry here... g_pd3dDevice->SetStreamSource( 0, g_pTriangleList_VB, 0, sizeof(Vertex) ); g_pd3dDevice->SetFVF( D3DFVF_MY_VERTEX ); // D3DPT_POINTLIST // D3DPT_LINELIST // D3DPT_LINESTRIP // D3DPT_TRIANGLELIST // D3DPT_TRIANGLESTRIP // D3DPT_TRIANGLEFAN g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, nNum / 3 ); g_pd3dDevice->EndScene(); ////////////////////////////////////////////////////////////////////////////////// D3DVIEWPORT9 vp5; vp5.X = 10 + (g_dwBackBufferWidth-20) / 3; vp5.Y = g_dwBackBufferHeight / 2; vp5.Width = (g_dwBackBufferWidth-20) / 3; vp5.Height = g_dwBackBufferHeight / 2; vp5.MinZ = 0.0f; vp5.MaxZ = 1.0f; g_pd3dDevice->SetViewport( &vp5 ); // Clear screen with D3DCOLOR_XRGB(0, 0, 0) g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); g_pd3dDevice->BeginScene(); // Render geometry here... g_pd3dDevice->SetStreamSource( 0, g_pTriangleStrip_VB, 0, sizeof(Vertex) ); g_pd3dDevice->SetFVF( D3DFVF_MY_VERTEX ); // D3DPT_POINTLIST // D3DPT_LINELIST // D3DPT_LINESTRIP // D3DPT_TRIANGLELIST // D3DPT_TRIANGLESTRIP // D3DPT_TRIANGLEFAN g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, nNum - 2 ); g_pd3dDevice->EndScene(); ////////////////////////////////////////////////////////////////////////////////// D3DVIEWPORT9 vp6; vp6.X = 10 + ((g_dwBackBufferWidth-20) / 3) * 2; vp6.Y = g_dwBackBufferHeight / 2; vp6.Width = (g_dwBackBufferWidth-20) / 3 + 10; vp6.Height = g_dwBackBufferHeight / 2; vp6.MinZ = 0.0f; vp6.MaxZ = 1.0f; g_pd3dDevice->SetViewport(&vp6); // Clear screen with D3DCOLOR_XRGB(0, 0, 0) g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); g_pd3dDevice->BeginScene(); // Render geometry here... g_pd3dDevice->SetStreamSource( 0, g_pTriangleFan_VB, 0, sizeof(Vertex) ); g_pd3dDevice->SetFVF( D3DFVF_MY_VERTEX ); // D3DPT_POINTLIST // D3DPT_LINELIST // D3DPT_LINESTRIP // D3DPT_TRIANGLELIST // D3DPT_TRIANGLESTRIP // D3DPT_TRIANGLEFAN g_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, nNum - 2); g_pd3dDevice->EndScene(); g_pd3dDevice->Present(NULL, NULL, NULL, NULL); }
框架代码我们在前面已经有说明,这里需要说明的是首先要定义顶点数据结构,这里定义了3D坐标和颜色。在创建设备后通过调用 IDirect3DDevice9::CreateVertexBuffer 方法创建我们需要的顶点缓冲区。在渲染时调用 IDirect3DDevice9::SetStreamSource 方法将顶点缓冲区绑定到设备数据流上,通过调用 IDirect3DDevice9::SetFVF 方法指定当前顶点数据流声明,通过调用 IDirect3DDevice9::DrawPrimitive 方法按照当前指定的顶点格式渲染无索引的顶点序列,最后显示出来。
下图为本例代码执行效果: