1. 程式人生 > >DirectX9.0 Texture紋理(貼圖)示例程式

DirectX9.0 Texture紋理(貼圖)示例程式

DirectX9.0 Texture紋理對映

將DirectX SDK 上的Texture略微修改,它是一個旋轉的空心圓柱體。我覺得用正方形能更好的理解紋理座標。其實在用遊戲引擎時,是不會關心紋理是如何具體對映的

1.紋理座標

DirectX中的紋理與OpenGL是類似的

紋理是一種點陣圖(2D 貼圖),可以把它貼上到Direct3D物體的表面。比如,可以獲取一張郵票的圖形貼上到正方形中,使正方形看起來像一張郵票。要使郵票保持合適的方向,以使影象井然有序的排列,則必須獲得形狀的每個頂點並在正方形上標記出來,以便郵票和正方形的形狀保持一致

DirectX假設紋理圖始終為1x1的正方形,其原點位於(0,0)處,右下角為(1,1).如圖所示:
在這裡插入圖片描述

紋理座標與頂點座標之間的對映關係:
在這裡插入圖片描述

定義頂點以及紋理座標(紋理作為物體的一部分):

// 自定義定點型別 新增紋理座標
struct CUSTOMVERTEX
{
	float x, y, z;
	unsigned long color;
	FLOAT tu, tv; // 紋理座標
};
// 構造組成物體的頂點,併為其指定紋理座標
CUSTOMVERTEX Vertices[] =
{
	   { -1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(255,255,255),0,1 }, // x, y, z, color,tu,tv
	   { -1.0f, 1.0f, 0.0f, D3DCOLOR_XRGB
(255,255,255), 0,0}, { 1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(255,255,255), 1,1}, { 1.0f, 1.0f, 0.0f, D3DCOLOR_XRGB(255,255,255), 1,0}, };

2.載入紋理圖片

//D3DXCreateTextureFromFile函式原型
HRESULT WINAPI D3DXCreateTextureFromFile(
  LPDIRECT3DDEVICE9 pDevice,      // 裝置物件
  LPCTSTR pSrcFile,               // 影象檔名
  LPDIRECT3DTEXTURE9 *
ppTexture // 用來儲存載入圖片的紋理物件例項 ); // 建立紋理 if( FAILED( D3DXCreateTextureFromFile( g_pd3dDevice, "objective-c.png", &g_pTexture ) ) ) { MessageBox(NULL, "Could not find objective-c.png", "Textures.exe", MB_OK); return E_FAIL; }

3.場景新增紋理步驟對映

  • 構造組成物體的頂點,併為其指定紋理座標
  • 用函式D3DCreateTextureFromFile為LPDIRECT3DTEXTURE9載入紋理
  • 繪製物體前,用函式SetTexture來設定與物體關聯的紋理

紋理複雜起來非常複雜,本文只涉及到紋理座標,程式碼實現:

//
// Globals
//
int width = 800;
int hight = 600;
IDirect3DDevice9* Device = 0; // Our rendering device
LPDIRECT3DTEXTURE9 g_pTexture = NULL; // Our texture
LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; // Buffer to hold vertices

//
// Framework Functions
//
// 自定義頂點型別,新增紋理座標
struct CUSTOMVERTEX
{
	float x, y, z;
	unsigned long color;
	FLOAT tu, tv; // 紋理座標
};
// 多了紋理,增加D3DFVF_TEX1
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)

bool Setup()
{
	// Turn off culling
	Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	// Turn off D3D lighting 
	Device->SetRenderState(D3DRS_LIGHTING, FALSE);
	// Turn on the zbuffer
	Device->SetRenderState(D3DRS_ZENABLE, TRUE);

	return true;
}

// ---------------------------------------------
// Name: InitGeometry()
// Desc: Create the Textures and Vertex buffer.
// ---------------------------------------------
HRESULT InitGeometry()
{
	// 建立紋理
	D3DXCreateTextureFromFile(Device, "texture.png", &g_pTexture); // texture.png與cpp同目錄存放,可省略路徑
	// 構造組成物體的頂點(正方形),併為其指定紋理座標
	CUSTOMVERTEX Vertices[] =
	{
		 { -1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(255,255,255),0,1 }, // x, y, z, color,tu,tv
		 { -1.0f, 1.0f, 0.0f, D3DCOLOR_XRGB(255,255,255), 0,0},
		 { 1.0f, -1.0f, 0.0f, D3DCOLOR_XRGB(255,255,255), 1,1},
		 { 1.0f, 1.0f, 0.0f, D3DCOLOR_XRGB(255,255,255), 1,0},
	};
	// 建立頂點緩衝區
	Device->CreateVertexBuffer(sizeof(Vertices), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL);
	VOID *pVertices;
	g_pVB->Lock(0, sizeof(Vertices), (void**)&pVertices, 0);
	memcpy(pVertices, Vertices, sizeof(Vertices));
	g_pVB->Unlock();

	return S_OK;
}
// -----------------------------------------------------------------
// Name: SetupMatrices()
// Desc: Sets up the world, view, and projection transform matrices.
// -----------------------------------------------------------------
VOID SetupMatrices()
{
	// 按照一定時間繞Y軸旋轉
	D3DXMATRIXA16 matWorld;
	D3DXMatrixIdentity(&matWorld);
	D3DXMatrixRotationY(&matWorld, timeGetTime() / 1000.0f);
	Device->SetTransform(D3DTS_WORLD, &matWorld);

	// 設定攝像頭的位置
	D3DXVECTOR3 vEyePt(0.0f, 3.0f, -5.0f);
	D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);
	D3DXMATRIXA16 matView;
	D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec);
	Device->SetTransform(D3DTS_VIEW, &matView);

	// 設定視椎體
	D3DXMATRIXA16 matProj;
	D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f);
	Device->SetTransform(D3DTS_PROJECTION, &matProj);
}

void Cleanup()
{
	d3d::Release(g_pTexture);
	d3d::Release(g_pVB);
}

bool Display(float timeDelta)
{
	if (Device) // Only use Device methods if we have a valid device.
	{
		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(100, 100, 100), 1.0f, 0);
		Device->BeginScene();
		SetupMatrices();
		// 繪製物體前,設定物體關聯的紋理
		Device->SetTexture(0, g_pTexture);
		// Render the vertex buffer contents
		Device->SetStreamSource(0, g_pVB, 0, sizeof(CUSTOMVERTEX));
		Device->SetFVF(D3DFVF_CUSTOMVERTEX); // 設定頂點格式
		// 兩個三角形組成矩形
		Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);

		Device->EndScene();
		// Swap the back and front buffers.
		Device->Present(0, 0, 0, 0);
	}
	return true;
}
int WINAPI WinMain(HINSTANCE hinstance,
	HINSTANCE prevInstance,
	PSTR cmdLine,
	int showCmd)
	{
		InitGeometry(); // 注意要在WinMain中呼叫該初始化函式
	}
	// ...其餘程式碼保持框架程式碼不變

執行結果(旋轉的馬里奧.gif):
在這裡插入圖片描述
完整框架程式碼及入門教程:DirectX9.0入門及例項程式