zoukankan      html  css  js  c++  java
  • 【笔记】《DirectX 9.0 3D游戏开发编程基础》:Direct3D初始化

    Direct3D初始化大概分为4个步骤:

    1.获取接口IDirect3D9的指针。(Direct3DCreate9函数调用)。

         该接口用户获取系统中物理硬件设备的信息并创建接口IDirect3DDevice9,此接口是一个C++对象,代表显示3D图形的物理硬件设备。

    2.检查设备性能(D3DCAPS9结构体),判断主显卡是否支持某些特性,比如是否支持顶点运算。创建IDirect3DDevice9之前,必须确定主显卡支持的特性。

    3.初始化D3DPRESENT_PARAMETER结构的一个实例,通过设置该结构体的成员变量来指定即将创建的借口IDirect3DDevice9的特性。

    4.利用已经初始化的D3DPRESENT_PARAMETER结构创建IDirect3DDevice9对象。

    以下是DirectX 9.0 3D游戏开发编程基础的基本程序框架(包含初始化的过程):

    d3dUtility.h

     InitD3D:该函数对应用程序主窗口进行了初始化(windows程序设计的基础,RegisterClass,CreateWindow,ShowWindow,UpdateWindow);

                 然后执行Direct3D初始化过程,返回一个指向已经创建好的IDirect3DDevice9接口的指针。

    EnterMsgLoop:封装了消息循环,参数为一个指向显示函数的函数指针。空闲处理期间显示场景。

    Release:模板函数是方便地释放COM接口并将其设置为NULL。

    Delete:模板函数是方便地删除自由堆对象,将其指针设置为NULL。

    WndProc:主窗口的窗口过程函数,针对不同类型的消息进行相对应的相应。

    #ifndef D3DUTILITY_H
    #define D3DUTILITY_H
    
    #include <d3dx9.h>
    #include <windows.h>
    #include <tchar.h>
    
    
    namespace d3d {
    
            bool InitD3D( HINSTANCE hInstance, int width, int height, bool windowed, D3DDEVTYPE deviceType, IDirect3DDevice9 **device);
    //[in] 应用实例 [in] 后台缓存的宽 [in]后台缓存的高 [in] 是否窗口或者全屏 [in] 设备类型 HAL或REF [out] 初始化成功的IDirect3DDevice指针 int EnterMsgLoop( bool (*ptr_display)(float timeDelta) );
    LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); template<class T> void Release(T t) { if( t ) { t->Release(); t = 0; } } template<class T> void Delete(T t) { if( t ) { delete t; t = 0; } } } #endif

    d3dUtility.cpp

    上述接口的具体实现部分。

    #include "d3dUtility.h"
    
    namespace d3d {
    
    	bool InitD3D( HINSTANCE hInstance, int width, int height, bool windowed, D3DDEVTYPE deviceType, IDirect3DDevice9 **device) {
    HWND hwnd; //窗口句柄
    WNDCLASS wndclass; //窗口类别,在CreateWindow之前需要RegisterClass , 针对WNDCLASS的参数可以了解一下API wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = (WNDPROC)d3d::WndProc; //WndProc wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = _T("Direct3D9App"); if( !RegisterClass(&wndclass) ) { MessageBox(0, _T("This program requires windows NT!"), 0, 0); return false; } hwnd = CreateWindow(_T("Direct3D9App")/*0*/,_T("Direct3D9App")/*0*/,WS_EX_TOPMOST/*WS_OVERLAPPEDWINDOW*/,0,0,width,height,0,0,hInstance,0); ::ShowWindow(hwnd,SW_SHOW/*0*/); ::UpdateWindow(hwnd);

    //完成了主窗口初始化的过程,以下部分实现Direct3D的初始化过程,并且设置IDirect3DDevice9指针 IDirect3D9 *_d3d9; _d3d9 = Direct3DCreate9(D3D_SDK_VERSION); //获取IDirect3D9的指针,进行设备的迭代,检测特性&获取IDirect3DDevice9指针准备 if( !_d3d9 ) { ::MessageBox(0, _T("Direct3DCreate9() - FAILED"), 0, 0); return false; } D3DCAPS9 caps; //检测图形设备的支持的特性 _d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps); int vp = 0; //是否支持硬件顶点运算 if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) { vp = D3DCREATE_HARDWARE_VERTEXPROCESSING; } else { vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING; } D3DPRESENT_PARAMETERS d3dpp; //D3DPRESENT_PARAMETERS设置,设置IDirect3DDevice的特性 ::ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS)); d3dpp.BackBufferWidth = width; d3dpp.BackBufferHeight = height; d3dpp.BackBufferFormat = D3DFMT_A8R8G8B8; d3dpp.BackBufferCount = 1; d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; d3dpp.MultiSampleQuality = 0; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = hwnd; d3dpp.Windowed = windowed; d3dpp.EnableAutoDepthStencil = true; d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; d3dpp.Flags = 0; d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; HRESULT hr = _d3d9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, vp, &d3dpp, device); if( FAILED(hr) ) { ::MessageBox(0, _T("CreateDevice() - Failed"), 0, 0); return false; } return true; } int EnterMsgLoop( bool (*ptr_display)(float timeDelta) ) { MSG msg; ::ZeroMemory( &msg, sizeof(MSG) ); static float lastTime = (float)timeGetTime(); while(msg.message != WM_QUIT) { if(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } else { //空闲的时候进行绘制 float currTime = (float)timeGetTime(); float timeDelta = (currTime - lastTime)*0.001f; ptr_display(timeDelta); lastTime = currTime; } } return msg.wParam; } LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch( msg ) { case WM_DESTROY: ::PostQuitMessage(0); break; case WM_KEYDOWN: if(wParam == VK_ESCAPE) //esc退出主窗口程序 ::DestroyWindow(hwnd); break; } return ::DefWindowProc(hwnd, msg, wParam, lParam); } }

    commonFunc.h

    此书中的3个例程函数:

    Setup:设置和初始化部分在此函数中进行,如分配资源,检查设备性能,设置应用程序状态。

    Cleanup:释放Setup函数中分配的任何资源,如分配的存储单元。

    Display:实现全部的绘制代码以及相邻帧之间应该执行的操作,如更新物体的位置。参数timeDelta为相邻帧的时间差,主要用于将动画与显示器的刷新频率保持同步。

    后续的章节的实现部分集中在这3个函数中,其他部分的代码设计到Direct3D的初始化和Windows程序设计的基本概念,在其他章节中改动很少。

    #ifndef COMMONFUNC_H
    #define COMMONFUNC_H
    
    #include "d3dUtility.h"
    IDirect3DDevice9  *Device = 0;
    bool windowed = true;
    bool Setup() {
    	return true;
    }
    
    void Cleanup() {
    	
    }
    
    bool Display(float timeDelta) {
    	if( Device ) {
    		Device->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
    		Device->Present(0, 0, 0, 0);
    	}
    	return true;
    } 
    
    #endif

    Entry.cpp

    window程序设计的入口,WinMain函数部分。

    #include "d3dUtility.h"
    #include "commonFunc.h"
    
    int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd ) {
    	if( !d3d::InitD3D(hInstance, 800, 600, true, D3DDEVTYPE_HAL, &Device )) {
    		::MessageBox(0,_T("InitD3D() - Failed"), 0, 0 );
    		return 0;
    	}
    	if( !Setup() ) {
    		::MessageBox(0,_T("Setup() - Failed"), 0, 0 );
    		return 0;
    	}
    	
    	d3d::EnterMsgLoop( Display );
    
    	Cleanup();
    
    	Device->Release();
    
    	return 0;
    }
    

     

    程序运行效果截图:

  • 相关阅读:
    Sqlserver 实际开发中表变量的用法
    Python Day 20 面向对象 (面向对象的组合用法,面向对象的三大特性
    Python Day 19 面向对象(初识面向对象)
    Python Day 18 常用模块(模块和包)
    Python Day 17 常用模块(常用模块一 时间模块,random模块,os模块,sys模块,序列化模块)
    Python Day 15 函数(递归函数、二分查找算法)
    Python Day 14 函数(内置函数,匿名函数(lambda表达式))
    Python Day 13 函数(迭代器,生成器,列表推导式,生成器表达式)
    Python Day 11 + Python Day 12 函数(函数名的应用,闭包,装饰器)
    Python Day 10 函数(名称空间,作用域,作用域链,加载顺序等; 函数的嵌套 global,nonlocal)
  • 原文地址:https://www.cnblogs.com/weixliu/p/4138947.html
Copyright © 2011-2022 走看看