zoukankan      html  css  js  c++  java
  • D3D的初始化

    要开始D3D编程,首先是要初始化D3D环境,SDK文档的tutorial将整个过程分为几部

    1. 创建一个窗体
    2. 初始化D3D
      • 获取IDirect3D9的指针
      • 检查设备的性能、对API的支持能力
      • 初始化D3DPRESENT_PARAMETERS
      • 使用D3DPRESENT_PARAMETER的参数创建IDirectDDevice9
    3. 处理消息
    4. 渲染&显示场景
    5. 关闭D3D,退出程序

    1. 创建窗体
      之前说过,D3D程序是在一个windows窗体的客户区进行绘制,D3D相当于画笔的话,这个窗体就是画布,所以在初始化D3D之前首先要有一个窗体,根据简单的Windows API编程回顾的内容,创建一个简单窗体并不难。

      • 定义窗口类
      WNDCLASS wclass;
      
      • 注册窗口类
      RegisterClass(&wclass);
      
      • 创建窗口
      CreateWindow(...);
      
    2. 初始化D3D
      一旦创建好了窗体,就可以在这个基础上进一步去初始化D3D,创建D3D设备,以在窗体这个画布上进行绘图,初始化D3D的过程可以分为四部。

      • 获取IDirect3D9的指针,游戏开发中最常用的就是COM配合DirectX技术,这儿IDirect3D9就是一个表示D3D9的COM接口,因此不能直接使用C++的new操作符
      LPDIRECT3D9 g_pD3D9;    //IDirect3D9 *g_pD3D9;
      g_pD3D9 = Direct3DCreate9(D3D_SDK_VERSION);
      
      • 检查设备性能,对API的支持程度(如硬件TnL,这个是比较老的固定功能流水线中所采用的一些东西,现代的可编程流水线已经见不着了)
      //以硬件TnL为例
      D3DCAPS9 d3dcap;
      int hwTnL = 0;
      g_pD3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps);
      if(caps.Devcaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
          hwTnL = D3DCREATE_HARDWARE_VERTEXPROCESSING;
      else
          hwTnL = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
      
      • 建立一个D3DPRESENT_PARAMETERS
      D3DPRESENT_PARAMETERS d3dpp;
      //按需设置d3dpp的各类属性
      
      • 建立D3D设备
      g_pD3D9->CreateDevice(D3DADAPTER,
                            D3DDEVTYPE,
                            HWND, BEHAVIOR_FLAGS
                            D3DPRESENT_PARAMETERS*,
                            IDirect3DDevice9 **);
      

    至此,D3D的初始化就完成了

    1. 处理消息
      就如简单的Windows API编程回顾中所述,游戏程序多数不是事件驱动的,因而可以使用PeekMessage处理消息

      MSG msg;
      while(PeekMessage(&msg, 0, 0, 0, 0))
      {
          if(msg.message == WM_QUIT)
              break;
          TranslateMessage(&msg);
          DispatchMessage(&msg);
      }
      //Game Codes
      
    2. 渲染&显示场景

      • 清除后台缓存,将后台缓存置为所设定的颜色,将深度或模板缓存设置为需要的值
      //IDirect3DDevice9::Clear
      g_pD3DDEV9->Clear(DWORD Count, const D3DRECT *pRects,
                        DWORD flags, D3DCOLOR Color, float Z, DWORD Stencil);
      
      • 向后台缓存绘制场景
      g_pD3DDEV9->BeginScene();
      //Render Codes
      g_pD3DDEV9->EndScene();
      
      • 提交下一帧后台缓存,仅仅是提交,还没有显示
      //IDirect3DDevice9::Present
      g_pD3DDEV9->Present(0,0,0,0);
      
    3. 关闭D3D,退出程序
      退出程序不困难,但之前要先关闭D3D。之前说了g_pD3D9和g_pD3DDEV9是两个COM接口指针,而COM不可以使用C++的new/delete操作符来创建和销毁,所以需要手动的来释放一下

    g_pD3D9->Release();
    g_pD3D9 = NULL;
    g_pD3DDEV9->Release();
    g_pD3DDEV9 = NULL;
    

    至此,整个D3D程序流程就结束了

    全部代码如下

    #include <windows.h>
    #include <d3d9.h>
    #include <strsafe.h>
    
    #pragma comment(lib, "d3d9.lib")
    
    
    LPDIRECT3D9			g_pD3D9;
    LPDIRECT3DDEVICE9	g_pD3D9dev;
    
    HWND hMain;
    
    bool initWinApp(HINSTANCE hInstance, int iCmdShow);
    LRESULT CALLBACK MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
    
    HRESULT D3DInit(HWND hWnd);
    void D3DRender();
    void D3DCleanup();
    
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmd, int iCmdShow)
    {
    	if( !initWinApp(hInstance, iCmdShow) )
    	{
    		::MessageBox(0, TEXT("initWinApp Failed!"), TEXT("ERROR"), MB_OK);
    		return 0;
    	}
    
    	if( SUCCEEDED(D3DInit(hMain)) )
    	{
    		::ShowWindow(hMain, iCmdShow);
    		::UpdateWindow(hMain);
    
    		MSG msg;
    		while( PeekMessage(&msg, 0, 0, 0, 0 ) )
    		{
    			if( msg.message == WM_QUIT )
    				break;
    			msg.message = WM_PAINT;
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
    		}
    	}
    
    	D3DCleanup();
    	UnregisterClass(L"D3DInit", hInstance);
    	return 0;
    
    
    }
    
    bool initWinApp(HINSTANCE hInstance, int iCmdshow)
    {
    	WNDCLASS wc;
    	wc.style		= CS_HREDRAW | CS_VREDRAW; 
    	wc.lpfnWndProc	= MsgProc;
    	wc.cbClsExtra	= 0;
    	wc.cbWndExtra	= 0;
    	wc.hInstance	= hInstance;
    	wc.hIcon		= ::LoadIcon(0, IDI_APPLICATION);
    	wc.hCursor		= ::LoadCursor(0, IDC_ARROW);
    	wc.hbrBackground= static_cast<HBRUSH>(::GetStockObject(WHITE_BRUSH));
    	wc.lpszMenuName	= 0;
    	wc.lpszClassName= TEXT("D3DInit");
    
    	if( !RegisterClass(&wc) )
    	{
    		::MessageBox(0, TEXT("RegisterClass Failed!"), TEXT("ERROR"), MB_OK);
    		return false;
    	}
    
    	if( (hMain = CreateWindow(TEXT("D3DInit"), TEXT("D3DInit"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
    		CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL)) == NULL)
    	{
    		::MessageBox(0, TEXT("CreateWindow Failed!"), TEXT("ERROR"), MB_OK);
    		return false;
    	}
    
    	return true;
    }
    
    HRESULT D3DInit(HWND hWnd)
    {
    	//acquire pointer to IDirect3D9
    	if( (g_pD3D9 = Direct3DCreate9(D3D_SDK_VERSION)) == NULL )
    	{
    		::MessageBox(0, TEXT("Direct3DCreate Failed!"), TEXT("ERROR"), MB_OK);
    		return E_FAIL;
    	}
    
    	//Check Device Capabilities, here we check the hardware TnL support
    	D3DCAPS9 caps;
    	g_pD3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps);
    	int hardwareTnL = 0;
    	if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
    		hardwareTnL = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    	else
    		hardwareTnL = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
    
    	//setup D3DPRESENT_PARAMETERS which defines the behavior of the D3D app 
    	D3DPRESENT_PARAMETERS d3dpp;
    	d3dpp.BackBufferWidth			= 800;
    	d3dpp.BackBufferHeight			= 600;
    	d3dpp.BackBufferCount			= 2;
    	d3dpp.BackBufferFormat			= D3DFMT_A8R8G8B8;
    	d3dpp.MultiSampleType			= D3DMULTISAMPLE_NONE;
    	d3dpp.MultiSampleQuality		= 0;
    	d3dpp.SwapEffect				= D3DSWAPEFFECT_DISCARD;
    	d3dpp.hDeviceWindow				= hMain;
    	d3dpp.Windowed					= 1;
    	d3dpp.EnableAutoDepthStencil	= TRUE;
    	d3dpp.AutoDepthStencilFormat	= D3DFMT_D24S8;
    	d3dpp.Flags						= 0;
    	d3dpp.FullScreen_RefreshRateInHz= D3DPRESENT_RATE_DEFAULT;
    	d3dpp.PresentationInterval		= D3DPRESENT_INTERVAL_IMMEDIATE;
    
    	//Create D3D device
    	if( FAILED(g_pD3D9->CreateDevice(D3DADAPTER_DEFAULT,
    									D3DDEVTYPE_HAL,
    									hWnd,
    									hardwareTnL,
    									&d3dpp,
    									&g_pD3D9dev)) )
    	{
    		MessageBox(0, TEXT("CreateDevice Failed"), TEXT("ERROR"), MB_OK);
    		return E_FAIL;
    	}
    
    	return S_OK;
    }
    
    LRESULT CALLBACK MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	switch( msg )
    	{
    	case WM_DESTROY:
    		::PostQuitMessage(0);
    		return 0;
    	case WM_PAINT:
    		D3DRender();
    		ValidateRect(hWnd, NULL);
    		return 0;
    	}
    	return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    
    void D3DRender()
    {
    	//Set BackBuffer
    	g_pD3D9dev->Clear(0, NULL, D3DCLEAR_TARGET,D3DCOLOR_XRGB( 0, 255, 0 ), 1.0f, 0 );
    
    	//Render in this section
    	if( SUCCEEDED(g_pD3D9dev->BeginScene()) )
    	{
    		g_pD3D9dev->EndScene();
    	}
    
    	//Present BackBuffer
    	g_pD3D9dev->Present(NULL, NULL, NULL, NULL);
    }
    
    void D3DCleanup()
    {
    	if( g_pD3D9dev != NULL )
    	{
    		g_pD3D9dev->Release();
    	}
    	if( g_pD3D9 != NULL )
    	{
    		g_pD3D9->Release();
    	}
    }
    
  • 相关阅读:
    维特比(Viterbi)算法解最优状态序列
    c#重要知识点复习1---程序流程控制
    学C# Hook原理及EasyHook简易教程
    EmguCV 绘画图形
    EmguCV创建/保存图片
    EmguCV中图像类型进行转换
    basler 相机拍照简单类综合Emgu.CV---得到图档--原创
    RotatedRect 类的用法
    EmguCv“线段” 结构类型学习
    aforge 学习-基本图像处理要用的类库
  • 原文地址:https://www.cnblogs.com/current/p/3984502.html
Copyright © 2011-2022 走看看