#ifndef __vertexH__ #define __vertexH__ struct Vertex { Vertex(){} Vertex( float x, float y, float z, float nx, float ny, float nz, float u, float v) { _x = x; _y = y; _z = z; _nx = nx; _ny = ny; _nz = nz; _u = u; _v = v; } float _x, _y, _z; float _nx, _ny, _nz; float _u, _v; // texture coordinates }; #define FVF_VERTEX (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1) #endif // __vertexH__
//============================================================================= // Author: xujie li (C) All Rights Reserved //============================================================================= #pragma once #include "stdafx.h" #include "template.h" //----------------------------------------------------------------------------- // 全局变量 //----------------------------------------------------------------------------- LPDIRECT3D9 g_pD3D = NULL; //Direct3D对象 LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //Direct3D设备对象 LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; //顶点缓冲区对象 LPDIRECT3DINDEXBUFFER9 g_pIB =NULL; //索引缓冲区对象 LPDIRECT3DTEXTURE9 g_pTexture = NULL; //纹理对象 //----------------------------------------------------------------------------- // 显示帧率 //----------------------------------------------------------------------------- ID3DXFont* Font = 0; DWORD FrameCnt = 0; float TimeElapsed = 0; float timeDelta =0; float FPS = 0; TCHAR TFPSString[100]; //----------------------------------------------------------------------------- // Desc: 顶点结构 //----------------------------------------------------------------------------- #define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE) //顶点格式 float g_fSpinX = 0.0f; float g_fSpinY = 0.0f; float g_fDisZ = 0.0f; HRESULT InitGeometry() { //创建纹理对象 if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, L"texture.jpg", &g_pTexture ) ) ) { MessageBox(NULL, L"创建纹理失败", L"Texture.exe", MB_OK); return E_FAIL; } g_pd3dDevice->CreateVertexBuffer( 24 * sizeof(Vertex), D3DUSAGE_WRITEONLY, FVF_VERTEX, D3DPOOL_MANAGED, &g_pVB, 0); Vertex* pVertices; g_pVB->Lock(0, 0, (void**)&pVertices, 0); // build box // fill in the front face vertex data pVertices[0] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f); pVertices[1] = Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f); pVertices[2] = Vertex( 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f); pVertices[3] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f); // fill in the back face vertex data pVertices[4] = Vertex(-1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f); pVertices[5] = Vertex( 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f); pVertices[6] = Vertex( 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f); pVertices[7] = Vertex(-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f); // fill in the top face vertex data pVertices[8] = Vertex(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f); pVertices[9] = Vertex(-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f); pVertices[10] = Vertex( 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f); pVertices[11] = Vertex( 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f); // fill in the bottom face vertex data pVertices[12] = Vertex(-1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f); pVertices[13] = Vertex( 1.0f, -1.0f, -1.0f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f); pVertices[14] = Vertex( 1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f); pVertices[15] = Vertex(-1.0f, -1.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f); // fill in the left face vertex data pVertices[16] = Vertex(-1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f); pVertices[17] = Vertex(-1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f); pVertices[18] = Vertex(-1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f); pVertices[19] = Vertex(-1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f); // fill in the right face vertex data pVertices[20] = Vertex( 1.0f, -1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f); pVertices[21] = Vertex( 1.0f, 1.0f, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f); pVertices[22] = Vertex( 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f); pVertices[23] = Vertex( 1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f); g_pVB->Unlock(); g_pd3dDevice->CreateIndexBuffer( 36 * sizeof(WORD), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &g_pIB, 0); WORD* pIndices = 0; g_pIB->Lock(0, 0, (void**)&pIndices, 0); // fill in the front face index data pIndices[0] = 0; pIndices[1] = 1; pIndices[2] = 2; pIndices[3] = 0; pIndices[4] = 2; pIndices[5] = 3; // fill in the back face index data pIndices[6] = 4; pIndices[7] = 5; pIndices[8] = 6; pIndices[9] = 4; pIndices[10] = 6; pIndices[11] = 7; // fill in the top face index data pIndices[12] = 8; pIndices[13] = 9; pIndices[14] = 10; pIndices[15] = 8; pIndices[16] = 10; pIndices[17] = 11; // fill in the bottom face index data pIndices[18] = 12; pIndices[19] = 13; pIndices[20] = 14; pIndices[21] = 12; pIndices[22] = 14; pIndices[23] = 15; // fill in the left face index data pIndices[24] = 16; pIndices[25] = 17; pIndices[26] = 18; pIndices[27] = 16; pIndices[28] = 18; pIndices[29] = 19; // fill in the right face index data pIndices[30] = 20; pIndices[31] = 21; pIndices[32] = 22; pIndices[33] = 20; pIndices[34] = 22; pIndices[35] = 23; g_pIB->Unlock(); return S_OK; } //----------------------------------------------------------------------------- // Desc: 设置观察矩阵和投影矩阵 //----------------------------------------------------------------------------- VOID SetWorldMatrix() { static long curTime=0; static float elapsetime=0; elapsetime = (timeGetTime()-curTime)/1000.0f; curTime = timeGetTime(); D3DXMATRIX matWorld; D3DXMATRIX matRotation; D3DXMATRIX matTranslation; D3DXMatrixRotationYawPitchRoll( &matRotation, D3DXToRadian(g_fSpinX), D3DXToRadian(g_fSpinY), 0.0f ); D3DXMatrixTranslation( &matTranslation, 0.0f, 0.0f, g_fDisZ ); matWorld = matRotation * matTranslation; g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); } VOID SetupViewandProjMatrices() { //创建并设置观察矩阵 D3DXVECTOR3 vEyePt( 0.0f, 0.0f, -10 ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); //创建并设置投影矩阵 D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f ); g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); } void SetLight() { } bool SetFont() { D3DXFONT_DESC df; ZeroMemory(&df, sizeof(D3DXFONT_DESC)); df.Height = 12; // in logical units df.Width = 12; // in logical units df.Weight = 500; // boldness, range 0(light) - 1000(bold) df.Italic = false; df.CharSet = GB2312_CHARSET; df.OutputPrecision = 0; df.Quality = 0; df.PitchAndFamily = 0; wcscpy(df.FaceName, L"Times New Roman"); // font style if(FAILED(D3DXCreateFontIndirect(g_pd3dDevice, &df, &Font))) { ::MessageBox(0, L"D3DXCreateFontIndirect() - FAILED", 0, 0); ::PostQuitMessage(0); } return true; } //----------------------------------------------------------------------------- // Desc: 初始化Direct3D //----------------------------------------------------------------------------- HRESULT InitD3D( HWND hWnd ) { if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL; D3DDISPLAYMODE d3ddm; if( FAILED( g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm ) ) ) { // TO DO: Respond to failure of GetAdapterDisplayMode return E_FAIL; } HRESULT hr; if( FAILED( hr = g_pD3D->CheckDeviceFormat( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16 ) ) ) { if( hr == D3DERR_NOTAVAILABLE ) // POTENTIAL PROBLEM: We need at least a 16-bit z-buffer! return E_FAIL; } // // Do we support hardware vertex processing? if so, use it. // If not, downgrade to software. // D3DCAPS9 d3dCaps; if( FAILED( g_pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps ) ) ) { // TO DO: Respond to failure of GetDeviceCaps return E_FAIL; } DWORD dwBehaviorFlags = 0; if( d3dCaps.VertexProcessingCaps != 0 ) dwBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING; else dwBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING; // // Everything checks out - create a simple, windowed device. // D3DPRESENT_PARAMETERS d3dpp; memset(&d3dpp, 0, sizeof(d3dpp)); d3dpp.BackBufferFormat = d3ddm.Format; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.Windowed = TRUE; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, dwBehaviorFlags, &d3dpp, &g_pd3dDevice ) ) ) { // TO DO: Respond to failure of CreateDevice return E_FAIL; } //禁用照明效果 g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); //设置剔出模式为不剔出任何面 g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); //g_pd3dDevice->SetRenderState ( D3DRS_FILLMODE, D3DFILL_WIREFRAME ); //设置变换矩阵 SetupViewandProjMatrices(); SetLight(); SetFont(); return S_OK; } //----------------------------------------------------------------------------- // Desc: 释放创建对象 //----------------------------------------------------------------------------- VOID Cleanup() { //释放纹理对象 if( g_pTexture != NULL ) g_pTexture->Release(); //释放顶点缓冲区对象 if( g_pVB != NULL ) g_pVB->Release(); //释放索引缓冲区对象 if( g_pIB != NULL ) g_pIB->Release(); //释放Direct3D设备对象 if( g_pd3dDevice != NULL) g_pd3dDevice->Release(); //释放Direct3D对象 if( g_pD3D != NULL) g_pD3D->Release(); } //----------------------------------------------------------------------------- // Desc: 渲染图形 //----------------------------------------------------------------------------- VOID Render(float timeDelta) { FrameCnt++; TimeElapsed += timeDelta; if(TimeElapsed >= 1.0f) { char FPSString[100]; FPS = (float)FrameCnt / TimeElapsed; D3DCAPS9 d3dCaps; g_pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL, &d3dCaps ); if( d3dCaps.VertexProcessingCaps != 0 ) sprintf(FPSString, "D3D9 %.2ffps HAL(hw vp)", FPS); else sprintf(FPSString, "D3D9 %.2ffps REF(simulate hw vp) ", FPS); int nLen = strlen(FPSString) + 1; FPSString[nLen] = '\0'; // mark end of string int nwLen = MultiByteToWideChar(CP_ACP, 0, FPSString, nLen, NULL, 0); MultiByteToWideChar(CP_ACP, 0, FPSString, nLen, TFPSString, nwLen); TimeElapsed = 0.0f; FrameCnt = 0; } //清空后台缓冲区 g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(45, 50, 170), 1.0f, 0 ); //开始在后台缓冲区绘制图形 if( SUCCEEDED( g_pd3dDevice->BeginScene() ) ) { RECT rect = {0, 0, 600, 500}; Font->DrawText(0,TFPSString,-1,&rect,DT_TOP | DT_LEFT, 0xffffff00); SetWorldMatrix(); g_pd3dDevice->SetTexture( 0, g_pTexture ); //设置纹理 g_pd3dDevice->SetStreamSource(0, g_pVB, 0, sizeof(Vertex)); g_pd3dDevice->SetIndices(g_pIB); g_pd3dDevice->SetFVF(FVF_VERTEX); g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0,24,0,12); g_pd3dDevice->EndScene(); } //将在后台缓冲区绘制的图形提交到前台缓冲区显示 g_pd3dDevice->Present( NULL, NULL, NULL, NULL ); } //----------------------------------------------------------------------------- // Desc: 消息处理 //----------------------------------------------------------------------------- LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { static POINT ptLastMousePosit; static POINT ptCurrentMousePosit; static bool bMousing; switch( msg ) { case WM_LBUTTONDOWN: { ptLastMousePosit.x = ptCurrentMousePosit.x = LOWORD (lParam); ptLastMousePosit.y = ptCurrentMousePosit.y = HIWORD (lParam); bMousing = true; } break; case WM_LBUTTONUP: { bMousing = false; } break; case WM_MOUSEMOVE: { ptCurrentMousePosit.x = LOWORD (lParam); ptCurrentMousePosit.y = HIWORD (lParam); if( bMousing ) { g_fSpinX -= (ptCurrentMousePosit.x - ptLastMousePosit.x); g_fSpinY -= (ptCurrentMousePosit.y - ptLastMousePosit.y); } ptLastMousePosit.x = ptCurrentMousePosit.x; ptLastMousePosit.y = ptCurrentMousePosit.y; } break; case WM_MOUSEWHEEL: { g_fDisZ +=(short)HIWORD (wParam)*0.01; } break; case WM_DESTROY: Cleanup(); PostQuitMessage( 0 ); return 0; case WM_PAINT: Render(timeDelta); ValidateRect( hWnd, NULL ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } //----------------------------------------------------------------------------- // Desc: 程序入口 //----------------------------------------------------------------------------- int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { WNDCLASSEX winClass; MSG uMsg; memset(&uMsg,0,sizeof(uMsg)); winClass.lpszClassName = L"MY_WINDOWS_CLASS"; winClass.cbSize = sizeof(WNDCLASSEX); winClass.style = CS_HREDRAW | CS_VREDRAW; winClass.lpfnWndProc = MsgProc; winClass.hInstance = hInstance; winClass.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON); winClass.hIconSm = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON); 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; HWND hWnd = CreateWindowEx( NULL, L"MY_WINDOWS_CLASS", L"Direct3D (DX9) - Initialization", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 640, 480, NULL, NULL, hInstance, NULL ); //初始化Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ) { if( SUCCEEDED(InitGeometry())) { //显示主窗口 ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd ); static float lastTime = (float)timeGetTime(); //进入消息循环 MSG msg; ZeroMemory( &msg, sizeof(msg) ); while( msg.message!=WM_QUIT ) { if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } else { float currTime = (float)timeGetTime(); float timeDelta = (currTime - lastTime)*0.001f; Render(timeDelta); //渲染图形 lastTime = currTime; } } } } UnregisterClass( L"ClassName", hInstance); return 0; }