DirectX编程基础

DirectX(Direct eXtension, DX)是由Microsoft创建的多媒体编程接口,它能够让多媒体软件程序在基于Windows的具有DirectX兼容硬件与驱动程序的计算机上运行,同时可保证硬件的高性能使用。DirectX包括两个方面:一是DirectX SDK,用于开发DirectX应用程序;二是DirectX Runtime,是一组动态链接库,用于开发和运行DirectX应用程序。而Direct3D主要负责3D效果的显示,下面主要介绍Direct3D的编程方法。

一、基本概念

1.1 Direct3D接口对象

Direct3D是基于组件对象模型COM的设计结构,因此应用程序需用通过COM接口对象的接口的指针执行COM接口对象的功能。

同时COM接口对象与C++类对象的区别是,C++类对象由new和delete控制对象的生存周期,而COM接口对象则通过控制该对象的引用计数来决定其生存周期,即一般调用Release来释放引用结束的接口。

编制基于Direct3D的程序,首先需要两个接口对象的指针,一是IDirect3D9接口对象的指针,可通过Direct3DCreate9函数获得;二是IDirect3DDevice9接口对象的指针,可利用IDirect3D9接口对象指针的CreateDevice函数获得。一般这两个指针定义为全局变量,可用于程序的任何地方。下面关于Direct3D的编程主要依靠于上述的IDirect3DDevice9接口对象指针。

LPDIRECT3D9             g_pD3D       = NULL; 
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; 

1.2 顶点与图元

Direct3D绘制图形的基础是预设的顶点坐标,在Direct3D中,可以创建自定义灵活顶点格式FVF,通过用一个简单宏来说明自定义的FVF格式,Direct3D就能够正确获取顶点的信息,如坐标、颜色等。具体编程是通过顶点缓存的创建、访问、关联、绘制等步骤实现,一般可用到CreateVertexBuffer、Lock、Unlock、SetStreamSource、DrawPrimitive等函数。

g_pd3dDevice->CreateVertexBuffer(8*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX,
		D3DPOOL_DEFAULT, &g_pVertexBuf, NULL);
CUSTOMVERTEX *pVertices = NULL;
g_pVertexBuf->Lock(0, 0,(void**)&pVertices, 0);
pVertices[0] = CUSTOMVERTEX(-5.0F,  5.0F, -5.0F, D3DCOLOR_XRGB(255,  0,  0));
/* Set the Vertex Value */
pVertices[7] = CUSTOMVERTEX( 5.0F, -5.0F, -5.0F, D3DCOLOR_XRGB(  0,255,  0));
g_pVertexBuf->Unlock();

对于复杂的对象(这种复杂很常见),更多地使用索引缓存的方法,索引缓存只记录要绘制顶点在顶点缓存中的索引值,这种方式避免了顶点数据的重复存储,缩小了程序的数据存储空间。具体编程需要在顶点缓存创建、访问的基础上,同样也需要创建、访问、关联、绘制索引缓存,相关的函数主要有CreateIndexBuffer、Lock、Unlock、SetIndices、DrawIndexedPrimitive等。

g_pd3dDevice->CreateIndexBuffer(36*sizeof(WORD), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &g_pIndexBuf, NULL);
WORD *pIndices = NULL;
g_pIndexBuf->Lock(0, 0, (void**)&pIndices, 0);
pIndices[0] = 0;  pIndices[1] = 1;  pIndices[2] = 2;
/* Set the Indices Value */
pIndices[33] = 4; pIndices[34] = 7; pIndices[35] = 6;
g_pIndexBuf->Unlock();

1.3 渲染状态

Direct3D提供了多种渲染状态来决定几何物体如何被渲染,它可用于控制Direct3D设备光栅化模型的行为,包括绘制物体的着色模式、雾化操作及其他光栅化操作等。

渲染状态可通过SetRenderState函数来实现,比较重要的状态有D3DRS_CULLMODE、D3DRS_SHADEMODE、D3DRS_FILLMODE等。

g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
g_pd3dDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);

二、程序框架

DXUT(DirectX Utility Library)是建立在Direct3D 9和Direct3D 10上的一个程序框架,它简化了Direct3D应用程序的开发。这里暂时并不使用该框架,仅采用Windows应用程序的创建方法来搭建Direct3D程序框架。

程序中关于Direct3D的部分主要包括Direct3D程序初始化、绘制3D场景、结束Direct3D程序等。具体介绍如下:

(1) Direct3D程序初始化,包括创建Direct3D接口、获取硬件设备信息、创建Direct3D设备接口、Direct3D接口的释放等;

(2) 绘制3D场景,包括清空背景、图形绘制准备、图形绘制、翻转等;

(3) 结束Direct3D程序,用来释放创建的对象,包括设备接口对象、顶点缓存、索引缓存等。

当然程序需要注意一些其他的东西,如头文件的包含、库文件的链接等,具体包括:<d3d9.h> <d3dx9.h> <dxerr.lib> <dxguid.lib> <d3d9.lib> <d3dx9.lib> <winmm.lib>等。

 

#include <d3d9.h>   /* 头文件包含 */

/* 链接库文件 d3d9.lib 和 d3dx9.lib */

/* 全局变量 */
LPDIRECT3D9             g_pD3D       = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // Our rendering device

/* 初始化Direct3D */
HRESULT InitD3D( HWND hWnd )
{
    // Create the D3D object, which is needed to create the D3DDevice.
    if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
        return E_FAIL;

    // Set up the structure used to create the D3DDevice. Most parameters are
    D3DPRESENT_PARAMETERS d3dpp; 
    ZeroMemory( &d3dpp, sizeof(d3dpp) );
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

    // Create the Direct3D device.
    if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pd3dDevice ) ) )
    {
		if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, hWnd,
                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                                      &d3dpp, &g_pd3dDevice ) ) )
			return E_FAIL;
    }

    // Other Adding codes	

    return S_OK;
}

/* 释放所有对象 */
VOID Cleanup()
{
    if( g_pd3dDevice != NULL) 
        g_pd3dDevice->Release();

    if( g_pD3D != NULL)
        g_pD3D->Release();
}

/* 渲染3D场景 */
VOID Render()
{
    if( NULL == g_pd3dDevice )
        return;

    // Clear the backbuffer to a blue color
    g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 );
    
    // Begin the scene
    if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
    {
        // Rendering of scene objects can happen here
    
        // End the scene
        g_pd3dDevice->EndScene();
    }

    // Present the backbuffer contents to the display
    g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}

/* 消息处理主循环 */
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch( msg )
    {
        case WM_DESTROY:
            Cleanup();
            PostQuitMessage( 0 );
            return 0;
    }
    return DefWindowProc( hWnd, msg, wParam, lParam );
}

/* 主函数部分 */
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
	// Register the window class
    WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L, 
                      GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
                      L"D3D Tutorial", NULL };
    RegisterClassEx( &wc );

    // Create the application's window
    HWND hWnd = CreateWindow( L"D3D Tutorial", L"D3D Tutorial", 
                              WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
                              GetDesktopWindow(), NULL, wc.hInstance, NULL );

    // Initialize Direct3D
    if( SUCCEEDED( InitD3D( hWnd ) ) )
    { 
        // Show the window
        ShowWindow( hWnd, SW_SHOWDEFAULT );
        UpdateWindow( hWnd );

		MSG mssg;

		PeekMessage( &mssg, NULL, 0, 0, PM_NOREMOVE);
		// run till completed
		while (mssg.message!=WM_QUIT) 
		{
			// is there a message to process?
			if (PeekMessage( &mssg, NULL, 0, 0, PM_REMOVE))
			{
				// dispatch the message
				TranslateMessage(&mssg);
				DispatchMessage(&mssg);
			} 
			else 
			{
	           	//No message to process
    			 Render();
     		}
		}
    }

    UnregisterClass( L"D3D Tutorial", wc.hInstance );
    return 0;
}


本文为个人读书笔记,主要着重于编程学习,参考文献包括:

[1] 郑阿奇. DirectX 3D游戏编程实用教程[M]. 北京:电子工业出版社, 2011.

[2] Introduction to 3D Game Programming with DirectX 9.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值