vc.net 遊戲開發 第四章 創建Direct3D渲染和顯示3D三角形

//*********************************************
//功能:創建Direct3D渲染和顯示3D三角形
//作者:張小斌
//時間:2005.4.1
//*********************************************
//防止鏈接出錯
#pragma comment(lib,"d3d9.lib")
#pragma comment(lib,"d3dx9.lib")
#pragma comment(lib,"dinput8.lib")
#pragma comment(lib,"dxguid.lib")

#include<windows.h>//windows程序你不包含着是不可能的
#include<d3d9.h>//即然是DX9程序那肯定是需要包含着個頭文件的

//接下來定義一個Windows類的宏名稱
#define MY_WINCLASS_NAME "Direct3d"
//定義定點的類型格式
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
//創建一個頂點緩衝區結構,用於創建定點緩衝區
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL;

HWND hWnd;

//養成好習慣先聲明一下
HRESULT InitMy3D(HWND hWnd);
void Cleanup();
LRESULT WINAPI MsgProc(HWND hWnd,UINT msg ,WPARAM wParam,LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrecInstance, LPSTR lpCmdLine, int nCmdShow);
void RenderSene();
HRESULT InitVB();

//記着程序是Direct3d編程時,我們必須先創建Direct3D對象,在程序結束的時候,也必須最後釋放該對象。
//爲了保存創建的Direct3D對象和設備,那我們就需要以下的兩個全局變量

//在這碰到點問題編譯的時候到這不能正常編譯,再把下面這兩個在手工的重寫一邊,別偷懶,一個字一個字的敲。
LPDIRECT3D9      pD3D = NULL;
LPDIRECT3DDEVICE9 pDev = NULL;
//頂點結構
struct CUSTOMVERTEX
{
FLOAT x, y, z; // x,y,z表示點的三維座標值,
    DWORD color;        // 頂點顏色
};

HRESULT InitVB()
{
//初始化3個頂點
CUSTOMVERTEX g_Vertices[] =
{
        //需要注意繪製的順序
 {  0.0f,  1.0f, 0.0f, D3DCOLOR_XRGB(255, 0 , 0 ), }, // x, y, z, color
         {  1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB( 0 ,255,255), },
         { -1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(255,255,255), }

};
//定義一個指針,用於複製頂點數據是指向定點緩衝區的內存結構
    VOID* pVertices;
//創建頂點緩衝區
if( FAILED( pDev->CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX,D3DPOOL_DEFAULT, &g_pVB, NULL ) ) )
    {
        return E_FAIL;
    }
//把頂點數據從頂點數組中複製到頂點緩衝區中
    if( FAILED( g_pVB->Lock( 0, sizeof(g_Vertices), (void**)&pVertices, 0 ) ) )
        return E_FAIL;
    memcpy( pVertices, g_Vertices, sizeof(g_Vertices) );
    g_pVB->Unlock();

    return S_OK;
}

//----------------------------------------------------------------------------------------------
//方法名:RenderSene()
//功  能:定義了一個渲染函數,這個函數完成渲染開關的打開,關閉操作以及展現後臺表面到客戶區域中
//注  意:
//----------------------------------------------------------------------------------------------
void RenderSene()
{
//檢查Direct3D設備是否創建,如果沒有創建就直接返回
if(NULL == pDev)
return;
//清除Direct3D設備的後臺表面,背景顏色RGB(0,0,0)
pDev->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(255,0,255),1.0f,0);
//大開3D渲染開關
if( SUCCEEDED( pDev->BeginScene() ) )
{
//進行3D渲染,在這裏設置渲染的定點格式,並調用DrawPrimitive完成頂點渲染的處理
//設置泫然的頂點來源
pDev->SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) );
//設置代渲染頂點的定點格式
pDev->SetFVF(D3DFVF_CUSTOMVERTEX);
//渲染指定了緩衝區來源的頂點
pDev->DrawPrimitive(D3DPT_TRIANGLELIST,0,1);
//關閉3D渲染開關
pDev->EndScene();
}
else
{
MessageBox(hWnd,"3D渲染開關未打開!","出錯!",MB_OK);

}
//展現後臺表面帶窗口的客戶區域中,即把渲染後的圖象顯示到窗口中
pDev->Present(NULL,NULL,NULL,NULL);

}

//到這就要開始寫方法了既然是DX9程序那就要初始化D3D的環境
//---------------------------------------------------------
//方法名:InitD3D()
//功 能:初始化D3D環境,函數創建了Direct3D對象和Direct3D設備。
//注 意:函數返回E_FAIL表示失敗,返回E_OK表示成功
//    說到這了就需要提到一些額外的知識
//  在Direct3D中,提供了兩個宏專門用於測試函數是否調用成功。
//        1. FAILED()----對該函數返回的錯誤進行測試,如果函數返回任何錯誤信息,該測試之爲真。
//    2.SUCCEEDED()--對函數執行是否成功進行測試,如函數執行成功,值爲真.
//---------------------------------------------------------

HRESULT InitMy3D(HWND hWnd)
{
if( NULL == ( pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;
//創建Direct3D對象,這是使用Direct3D的第一步操作
if(NULL == ( pD3D = Direct3DCreate9( D3D_SDK_VERSION )))
return E_FAIL;

//獲取當前Windows桌面的顯示模式,保存到定義的d3ddm結構中
D3DDISPLAYMODE d3ddm;
//到這用到了上面“注意”中提到的宏。
//看好了當寫到pD3D->時輸入了">"這個符號而沒有出現下拉列表那就是前面你寫錯了,趕快去查錯。
if( FAILED( pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT,&d3ddm)))
return E_FAIL;

//定義Presend結構
D3DPRESENT_PARAMETERS d3dpp;

//把結構清零,創建設備時,結構成員值爲0表示使用缺省值
ZeroMemory(&d3dpp,sizeof(d3dpp));

//制定創建的Direct3D是支持窗口的設備
d3dpp.Windowed = TRUE;

//指定交換效果爲D3DSWAPEFFECT_DISCARD,即把後臺表面顯示到前臺表面以後
//原來的後臺表面包含的信息自動丟失
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

//後臺緩衝區的點格式與當前顯示模式的點格式一致
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

//D3D對象都創建了那就該創建Direct3D設備了
//1。使用主顯卡創建設備,參數D3DADAPTER_DEFAULT.(如果你的計算機裏插了兩塊顯卡那你就的指定清楚,看來微軟早遇見了PCI_E的出現)
//2。設備類型爲硬件抽象設備,使用硬件加速能,參數D3DDEVTYPE_HAL
//3。使用前面創建的窗口用於目標表面的顯示,參數hWnd
//4。指定設備對於頂點的處理能力爲軟件處理頂點,這是爲了讓所有的顯卡制持,參數
// D3DCREATE_SOFTWARE_VERTEXPROCESSING

if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&pDev)))
{
return E_FAIL;
}
return S_OK;
//把上面的看明白了最後的三行你就知道是幹嗎的了
}

//-----------------------------------------------------------------------------------------------
//方法名:Cleanup()
//功  能:釋放創建過的Direct3D對象和設備
//注  意:C++可不是JAVA有垃圾回收機制,你得把你申請的資源在用完後還給電腦
//-----------------------------------------------------------------------------------------------
void Cleanup()
{
//在上次建立D3D設備中我們沒有建立頂點緩衝區,這次用到了,用完了就的釋放
if( g_pVB != NULL )        
        g_pVB->Release();
//釋放時的順序爲先釋放創建的設備後釋放對象
if(pDev !=NULL)
pDev->Release();
//Direct3D對象最先創建,但需要最後釋放
if(pD3D != NULL)
pD3D->Release();
return;
//如果你不明白爲何這樣釋放,去把你的C++在複習一下
}
//-------------------------------------------------------------------------------------------------------------------
//方法名:MsgProc()
//功  能:Windows的詳細處理函數
//注  意:消息是遊戲程序的另一個重點,它用於處理鍵盤,鼠標,遙杆的響應以及觸發的事件
//        如:主角揮劍砍怪物會發生劍和怪物的碰撞,就需要把這一消息處理是打怪物沒打上還是打上,打傷了如何計算傷害等等。
//-------------------------------------------------------------------------------------------------------------------
LRESULT WINAPI MsgProc(HWND hWnd,UINT msg ,WPARAM wParam,LPARAM lParam)
{
switch(msg)
{
case WM_DESTROY:
//調用Cleanup函數清除3D對象和設備
Cleanup();
PostQuitMessage(0);
return 0;
case WM_RBUTTONDOWN:
RenderSene();
return 0;
}
return DefWindowProc(hWnd,msg,wParam,lParam);
}
//--------------------------------------------------------------------------------------------------------------------
//方法名:WinMain()
//功  能:Windows主函數,程序啓動時,從這裏開始
//注  意:你要是不寫他,你就完了
//--------------------------------------------------------------------------------------------------------------------
int APIENTRY WinMain(HINSTANCE hInstance,    //hInstance:表示該應用程序的句柄
 HINSTANCE hPrecInstance,//hPrevInstance:爲了保持與16位windows應用程序的兼容性
 LPSTR lpCmdLine,        //lpCmdLine:指向命令行參數字符串的指針
 int nCmdShow)           //nCmdShow:指定應用程序窗口顯示方式的整數

{
//定義一個類,指定消息的處理函數爲MsgProc
WNDCLASSEX wc = {sizeof(WNDCLASSEX),CS_CLASSDC,MsgProc,0l,0l,
 GetModuleHandle(NULL),NULL,NULL,NULL,NULL,
 MY_WINCLASS_NAME,NULL};
//註冊這個窗口類
RegisterClassEx(&wc);

//創建應用程序窗口
hWnd = CreateWindow(MY_WINCLASS_NAME,"3D遊戲編程--渲染和顯示3D三角形",
WS_OVERLAPPEDWINDOW,100,100,400,300,
GetDesktopWindow(),NULL,wc.hInstance,NULL);
//調用InitMy3D函數對3D對象和設備初始化,傳入的參數爲窗口的句柄hWnd
if(SUCCEEDED(InitMy3D( hWnd)))
{
//調用InitVB函數初始化頂點結構
if(SUCCEEDED(InitVB()))
{
//顯示窗口
ShowWindow(hWnd,SW_SHOWDEFAULT);
UpdateWindow(hWnd);

//程序主循環,進行窗口消息的分發,消息的處理在MsgProc函數中完成
MSG msg;
ZeroMemory( &msg, sizeof(msg) );
while( msg.message!=WM_QUIT )
            {
                if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
                {
                    TranslateMessage( &msg );
                    DispatchMessage( &msg );
                }
else
{
RenderSene();
}
}
}
}


//註銷窗口類
UnregisterClass(MY_WINCLASS_NAME,wc.hInstance);

return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章