Direct3D几何流水线

 Direct3D几何流水线由世界变换、观察变换、投影变换和视口变换几个部分组成。

一、坐标空间

1.1 局部坐标系

用于描述物体自身属性的独立坐标系,它相对于物体中心位置构成一个模型空间。在该模型空间,描述了物体的方向和构成物体的元素相对于物体中心的位置。

1.2 世界坐标系

用于建立一个描述其他坐标系所需要的参考框架,以便指定物体在该坐标系中的位置、方向及大小。其描述的空间称为世界空间,包含了所有的物体模型,并且这些物体模型被组合到一起而形成一个场景。

1.3 观察坐标系

用于指定观察三维空间中的物体的方向和位置,其原点指定了摄像机的位置。它定义了摄像机的屏幕可视区域,可产生观察物体“近大远小”的效果。

二、数学对象

2.1 向量

D3DXVECTOR3是Direct3D中的向量,当然也有D3DXVECTOR2和D3DXVECTOR4两种形式,并且重载了加减乘除、赋值等操作与求模、规格化、点积、叉积等运算。

2.2 矩阵

D3DMATRIX是Direct3D中的矩阵,表示4*4的矩阵,其许多操作可参见SDK帮助。

三、几何变换

3.1 世界变换

包括平移、旋转、缩放变换,相关函数有D3DXMatrixTranslation、D3DXMatrixRotation、D3DXMatrixSaling等,应用到设备采用SetTransform(D3DTS_WORLD, &matWorld)。

3.2 观察变换

指定虚拟摄像机的位置、观察点位置及正方向,相关函数有D3DXMatrixLookAtLH等,应用到设备采用SetTransform(D3DTS_VIEW,&matView)。

3.3 投影变换

将位于视截体内的物体模型映射到投影窗口中,相关函数有D3DXMatrixPerspectiFovLH等,应用到设备采用SetTransform(D3DTS_PROJECTION,&matProj)。

3.4 视口变换

将投影窗口中的图像转换到显示屏幕的程序窗口中,视口由D3DVIEWPORT9描述,通过调用SetViewport函数就可以自动完成视口变换。

四、程序实例

下面创建的程序实现一个立方体分别绕X、Y和Z轴旋转的效果。 

#include <d3d9.h>
#include <d3dx9.h>

//Make sure the libraries d3d9.lib and d3dx9.lib are linked


//Add this source to your project

//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
LPDIRECT3D9             g_pD3D       = NULL; // Used to create the D3DDevice
LPDIRECT3DDEVICE9       g_pd3dDevice = NULL; // Our rendering device

LPDIRECT3DVERTEXBUFFER9 g_pVertexBuf = NULL;
LPDIRECT3DINDEXBUFFER9  g_pIndexBuf  = NULL;

struct CUSTOMVERTEX
{
	FLOAT _x,_y,_z;
	DWORD _color;
	CUSTOMVERTEX(FLOAT x, FLOAT y, FLOAT z, DWORD color)
		:_x(x),_y(y),_z(z),_color(color){}
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)


//-----------------------------------------------------------------------------
// Name: InitD3D()
// Desc: Initializes 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
    // zeroed out. We set Windowed to TRUE, since we want to do D3D in a
    // window, and then set the SwapEffect to "discard", which is the most
    // efficient method of presenting the back buffer to the display.  And 
    // we request a back buffer format that matches the current desktop display 
    // format.
    D3DPRESENT_PARAMETERS d3dpp; 
    ZeroMemory( &d3dpp, sizeof(d3dpp) );
    d3dpp.Windowed = TRUE;
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;

    // Create the Direct3D device. Here we are using the default adapter (most
    // systems only have one, unless they have multiple graphics hardware cards
    // installed) and requesting the HAL (which is saying we want the hardware
    // device rather than a software one). Software vertex processing is 
    // specified since we know it will work on all cards. On cards that support 
    // hardware vertex processing, though, we would see a big performance gain 
    // by specifying hardware vertex processing.
    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;

    }

    // 创建顶点缓存,填充顶点数据
	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));
	pVertices[1] = CUSTOMVERTEX(-5.0F,  5.0F,  5.0F, D3DCOLOR_XRGB(  0,255,  0));
	pVertices[2] = CUSTOMVERTEX( 5.0F,  5.0F,  5.0F, D3DCOLOR_XRGB(  0,  0,255));
	pVertices[3] = CUSTOMVERTEX( 5.0F,  5.0F, -5.0F, D3DCOLOR_XRGB(255,255,  0));
	pVertices[4] = CUSTOMVERTEX(-5.0F, -5.0F, -5.0F, D3DCOLOR_XRGB(  0,  0,255));
	pVertices[5] = CUSTOMVERTEX(-5.0F, -5.0F,  5.0F, D3DCOLOR_XRGB(255,255,  0));
	pVertices[6] = CUSTOMVERTEX( 5.0F, -5.0F,  5.0F, D3DCOLOR_XRGB(255,  0,  0));
	pVertices[7] = CUSTOMVERTEX( 5.0F, -5.0F, -5.0F, D3DCOLOR_XRGB(  0,255,  0));
	g_pVertexBuf->Unlock();

	// 创建索引缓存,填充索引数据
	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;
	pIndices[3] = 0;  pIndices[4] = 2;  pIndices[5] = 3;
	pIndices[6] = 0;  pIndices[7] = 3;  pIndices[8] = 7;
	pIndices[9] = 0;  pIndices[10] = 7; pIndices[11] = 4;
	pIndices[12] = 0; pIndices[13] = 4; pIndices[14] = 5;
	pIndices[15] = 0; pIndices[16] = 5; pIndices[17] = 1;
	pIndices[18] = 2; pIndices[19] = 6; pIndices[20] = 7;
	pIndices[21] = 2; pIndices[22] = 7; pIndices[23] = 3;
	pIndices[24] = 2; pIndices[25] = 5; pIndices[26] = 6;
	pIndices[27] = 2; pIndices[28] = 1; pIndices[29] = 5;
	pIndices[30] = 4; pIndices[31] = 6; pIndices[32] = 5;
	pIndices[33] = 4; pIndices[34] = 7; pIndices[35] = 6;
	g_pIndexBuf->Unlock();

    return S_OK;
}




//-----------------------------------------------------------------------------
// Name: Cleanup()
// Desc: Releases all previously initialized objects
//-----------------------------------------------------------------------------
VOID Cleanup()
{
    if( g_pd3dDevice != NULL) 
        g_pd3dDevice->Release();

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




//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Draws the scene
//-----------------------------------------------------------------------------
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() ) )
    {
        // 世界变换
		D3DXMATRIX matWorld, Rx, Ry, Rz;
		D3DXMatrixIdentity(&matWorld);
		D3DXMatrixRotationX(&Rx, ::timeGetTime()/1000.0f);
		D3DXMatrixRotationY(&Ry, ::timeGetTime()/1000.0f);
		D3DXMatrixRotationZ(&Rz, ::timeGetTime()/1000.0f);
		matWorld = Rx * Ry * Rz * matWorld;
		g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);
		// 观察变换
		D3DXMATRIX matView;
		D3DXVECTOR3 vEye(0.0f,  0.0f, -30.0f);
		D3DXVECTOR3 vAt(0.0f,  0.0f,   0.0f);
		D3DXVECTOR3 vUp(0.0f,  1.0f,   0.0f);
		D3DXMatrixLookAtLH(&matView, &vEye, &vAt, &vUp);
		g_pd3dDevice->SetTransform(D3DTS_VIEW,&matView);
		// 投影变换
		D3DXMATRIX matProj;		
		D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4.0f, 1.0f, 1.0f, 1000.0f);
		g_pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj);
		// 视口变换
		D3DVIEWPORT9 vp = {0, 0, 300, 250, 0, 1};
		g_pd3dDevice->SetViewport(&vp);
		// 设置渲染状态
		g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
		g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
		g_pd3dDevice->SetRenderState(D3DRS_FILLMODE,D3DFILL_WIREFRAME);
		// 渲染三角形
		g_pd3dDevice->SetStreamSource(0, g_pVertexBuf, 0, sizeof(CUSTOMVERTEX));
		g_pd3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
		g_pd3dDevice->SetIndices(g_pIndexBuf);
		g_pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 8, 0, 12);
    
        // End the scene
        g_pd3dDevice->EndScene();
    }

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




//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: The window's message handler
//-----------------------------------------------------------------------------
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 );
}




//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: The application's entry point
//-----------------------------------------------------------------------------
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 01: CreateDevice", 
                              WS_OVERLAPPEDWINDOW, 100, 100, 640, 480,
                              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?
				// Then do your game stuff here
    			 Render();
     		}
		}
    }

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

 

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

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

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值