两天了,不知道一直在忙什么。不想浪费时间继续directX的学习。闲话少说。。。步入正题。。
前天把管道渲染基本流程过了一遍,现在一起看看,实际的代码是怎样实现的。
#include <d3dx9.h> #define MAX_LOADSTRING 100 // 全局变量: HINSTANCE hInst; // 当前实例 TCHAR szTitle[MAX_LOADSTRING]; // 标题栏文本 TCHAR szWindowClass[MAX_LOADSTRING]; // 主窗口类名 LPDIRECT3D9 g_pD3D = NULL; LPDIRECT3DDEVICE9 g_pD3DDevice = NULL; LPDIRECT3DVERTEXBUFFER9 g_pVertexBuffer = NULL; // Buffer to hold vertices //定义顶点信息的结构体 struct CUSTOMVERTEX { FLOAT x, y, z, rhw; // The transformed position for the vertex. DWORD colour; // The vertex colour. }; //定义自由顶点格式 #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE) //定义释放COM对象的宏 #define SafeRelease(pObject) if(pObject != NULL) {pObject->Release(); pObject=NULL;} // 此代码模块中包含的函数的前向声明: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM); //初始化D3D设备 HRESULT InitialiseD3D(HWND hWnd) { //First of all, create the main D3D object. If it is created successfully we //should get a pointer to an IDirect3D8 interface. //取得D3D9的对象 g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); if(g_pD3D == NULL) { return E_FAIL; } //得到当前的显示模式 //Get the current display mode D3DDISPLAYMODE d3ddm; if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) { return E_FAIL; } //创建一个D3D设备 //Create a structure to hold the settings for our device D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); //Fill the structure. //We want our program to be windowed, and set the back buffer to a format //that matches our current display mode d3dpp.Windowed = TRUE;//全屏模式还是窗口模式 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;//后台缓冲区复制到前台时,清除后台缓冲区内容 d3dpp.BackBufferFormat = d3ddm.Format;//屏幕的显示模式 //创建一个Direct3D设备 //Create a Direct3D device. if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDevice))) { return E_FAIL; } return S_OK; } HRESULT InitialiseVertexBuffer() { VOID* pVertices; //顶点信息数组 //Store each point of the triangle together with it's colour CUSTOMVERTEX cvVertices[] = { {250.0f, 100.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(255, 0, 0),}, //Vertex 1 - Red (250, 100) {400.0f, 350.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 255, 0),}, //Vertex 2 - Green (400, 350) {100.0f, 350.0f, 0.5f, 1.0f, D3DCOLOR_XRGB(0, 0, 255),}, //Vertex 3 - Blue (100, 350) }; //通过设备创建顶点缓冲 //Create the vertex buffer from our device if(FAILED(g_pD3DDevice->CreateVertexBuffer(3 * sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVertexBuffer,NULL))) { return E_FAIL; } //锁定顶点缓冲,并得到一个存放顶点信息的缓冲区的指针 //Get a pointer to the vertex buffer vertices and lock the vertex buffer if(FAILED(g_pVertexBuffer->Lock(0, sizeof(cvVertices), (void**)&pVertices, 0))) { return E_FAIL; } //复制顶点信息 //Copy our stored vertices values into the vertex buffer memcpy(pVertices, cvVertices, sizeof(cvVertices)); //解锁顶点缓冲区 //Unlock the vertex buffer g_pVertexBuffer->Unlock(); return S_OK; } void Render() { if(g_pD3DDevice == NULL) { return; } //Clear the backbuffer to black //清空后备缓冲区为黑色 g_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); //Begin the scene //开始绘制场景 g_pD3DDevice->BeginScene(); //Rendering our triangle //渲染三角形 g_pD3DDevice->SetStreamSource(0, g_pVertexBuffer, 0, sizeof(CUSTOMVERTEX)); g_pD3DDevice->SetFVF(D3DFVF_CUSTOMVERTEX); g_pD3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 1); //End the scene //结束绘制场景 g_pD3DDevice->EndScene(); //Filp the back and front buffers so that whatever has been rendered on the back buffer //will now be visible on screen (front buffer). //翻页显示 g_pD3DDevice->Present(NULL, NULL, NULL, NULL); } //释放所使用到的所有COM对象 void CleanUp() { SafeRelease(g_pVertexBuffer); SafeRelease(g_pD3DDevice); SafeRelease(g_pD3D); } //游戏循环 void GameLoop() { //进入游戏循环 MSG msg; BOOL fMessage; PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE); while(msg.message != WM_QUIT) { fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE); if(fMessage) { //处理消息 TranslateMessage(&msg); DispatchMessage(&msg); } else { //No message to process, so render the current scene //如果没有消息,则渲染当前的场景 Render(); } } } int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { //Register the window class //注册Windows的窗口类 WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_CLASSDC, WndProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, "D3DDrawGraphics", NULL}; RegisterClassEx(&wc); //Create the application's window //创建一个窗口 HWND hWnd = CreateWindow("D3DDrawGraphics", "D3D绘制简单图形", WS_OVERLAPPEDWINDOW, 50, 50, 500, 500, GetDesktopWindow(), NULL, wc.hInstance, NULL); //Initialize Direct3D //初始化Direct3D if(SUCCEEDED(InitialiseD3D(hWnd))) { //Show our window //显示窗口 ShowWindow(hWnd, SW_SHOWDEFAULT); UpdateWindow(hWnd); //Initialize Vertex Buffer //初始化顶点缓冲 if(SUCCEEDED(InitialiseVertexBuffer())) { //Start game running: Enter the game loop //开始游戏: 进入游戏循环 GameLoop(); } } CleanUp(); //撤销窗口类的注册 UnregisterClass("D3DDrawGraphics", wc.hInstance); return 0; } // // 函数: MyRegisterClass() // // 目的: 注册窗口类。 // // 注释: // // 仅当希望在已添加到 Windows 95 的 // “RegisterClassEx”函数之前此代码与 Win32 系统兼容时, // 才需要此函数及其用法。调用此函数 // 十分重要,这样应用程序就可以获得关联的 // “格式正确的”小图标。 // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_MY); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCTSTR)IDC_MY; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); } // // 函数: InitInstance(HANDLE, int) // // 目的: 保存实例句柄并创建主窗口 // // 注释: // // 在此函数中,我们在全局变量中保存实例句柄并 // 创建和显示主程序窗口。 // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // 将实例句柄存储在全局变量中 hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // 函数: WndProc(HWND, unsigned, WORD, LONG) // // 目的: 处理主窗口的消息。 // // WM_COMMAND - 处理应用程序菜单 // WM_PAINT - 绘制主窗口 // WM_DESTROY - 发送退出消息并返回 // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_DESTROY: PostQuitMessage(0); return 0; break; case WM_KEYUP: switch (wParam) { case VK_ESCAPE: //User has pressed the escape key, so quit DestroyWindow(hWnd); return 0; break; } break; } return DefWindowProc(hWnd, message, wParam, lParam); } // “关于”框的消息处理程序。 LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; }