DirectX9:基礎篇 紋理

一.簡介

紋理映射是一種爲三角形賦予圖像數據的技術緩存

在 Direct3D 中一個紋理是經過 IDirect3DTexture9 接口來表示,一個紋理是一個像素矩陣的表面被映射到三角形上this

 

二.紋理座標

Direct3D 使用一個紋理座標系統,它是由水平方向的 軸(向右爲正)和豎直方向 v 軸(向下爲正)構成spa

 

// 紋理座標系統表示3d

struct Vertexrest

{code

  float _x, _y, _z;orm

  float _nx, _ny, _nz;blog

  float _u, _v;接口

  static const DWORD FVF;
};
圖片

const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;

 

三.建立紋理

1.D3DXCreateTextureFromFile()

紋理數據能夠從存儲在磁盤中的圖片文件中讀取,放入 IDirect3DTexture9 抽象紋理類型

支持的圖片格式有: BMP DDS  DIB JPG  PNG  TGA

 

HRESULT D3DXCreateTextureFromFile(

  LPDIRECT3DDEVICE9 pDevice,

  LPCSTR pSrcFile,

  LPDIRECT3DTEXTURE9* ppTexture

);

 

HRESULT IDirect3DDevice9::SetTexture(

  DWORD Stage,

  IDirect3DBaseTexture9* pTexture

);

 

// 建立紋理
IDirect3Dtexture9* _stonewall;
D3DXCreateTextureFromFile(_device, "stonewall.bmp", &_stonewall);

// 設置紋理
Device->SetTexture(0, _stonewall);

 

四.過濾器

紋理被映射到屏幕中的三角形上,有可能紋理和三角形不同大,當出現須要對紋理進行變形的時候,就要用過濾(Filtering)來讓變形平滑的技術

Direct3D提供了三種不一樣的過濾器,每種的品質級別和速度各不相同

 

1.Nearest point sampling

默認的過濾方法,品質最差,速度最快

Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);

 

2.Linear filtering

推薦使用,過濾產生的效果好

Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

 

3.Anisotropic filtering

過濾產生的品質最好,處理時間最長

Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);

 

4.Mipmaps過濾器

若是顯卡支持Mipmaps,Direct3D會自動選擇與三角形最匹配的Mipmap

Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);  // 不使用 mipmap
Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);

 

五.尋址模式

紋理座標必須指定在[0, 1]之間

Direct3D的尋址模式有四種: 環繞紋理尋址模式 邊框顏色紋理尋址模式  截取紋理尋址模式 鏡像紋理尋址模式

1.環繞紋理尋址模式(wrap address mode)

if (::GetAsyncKeyState('W') & 0x8000f)
{
    Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
    Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);   
}

 

2.邊框顏色紋理尋址模式(border color address mode)

if (::GetAsyncKeyState('B') & 0x8000f)
{
    Device>SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
    Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
    Device->SetSamplerState(0, D3DSAMP_BORDERCOLOR, 0x000000ff);
}

 

3.截取紋理尋址模式(clamp address mode)

if (::GetAsyncKeyState('C') & 0x8000f)
{
    Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
    Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
}

 

4.鏡像紋理尋址模式(mirror address mode)

if (::GetAsyncKeyState('M') & 0x8000f)
{
    Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
    Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
}

 

六.例子

1.不過濾紋理

#include "d3dUtility.h"

IDirect3DDevice9* Device = 0;

const int Width = 640;
const int Height = 480;

IDirect3DVertexBuffer9* Quad = 0;
IDirect3DTexture9* Tex = 0;

struct Vertex
{
	Vertex(){}

	float _x, _y, _z;
	float _nx, _ny, _nz;
	float _u, _v;

	Vertex(float x, float y, float z,
		  float nx, float ny, float nz,
		  float u, float v)
	{
		_x = x; _y = y; _z = z;
		_nx = nx; _ny = ny; _nz = nz;
		_u = u; _v = v;
	}

	static const DWORD FVF;
};

const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;

bool Setup()
{
	Device->CreateVertexBuffer(
		6 * sizeof(Vertex),
		D3DUSAGE_WRITEONLY,
		Vertex::FVF,
		D3DPOOL_MANAGED,
		&Quad,
		0);

	Vertex* v;
	Quad->Lock(0, 0, (void**)&v, 0);

	v[0] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
	v[1] = Vertex(-1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
	v[2] = Vertex(1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);

	v[3] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f);
	v[4] = Vertex(1.0f, 1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f);
	v[5] = Vertex(1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f);

	Quad->Unlock();

	// 加載紋理文件
	D3DXCreateTextureFromFile(Device, "a.bmp", &Tex);
	Device->SetTexture(0, Tex);

	Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

	Device->SetRenderState(D3DRS_LIGHTING, false);

	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(
		&proj,
		D3DX_PI * 0.5f,
		(float)Width / (float)Height,
		1.0f,
		1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &proj);

	return true;
}

void Cleanup()
{
	d3d::Release<IDirect3DVertexBuffer9*>(Quad);
	d3d::Release<IDirect3DTexture9*>(Tex);
}

bool Display(float timeDelta)
{
	if (Device)
	{

		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
		Device->BeginScene();

		Device->SetStreamSource(0, Quad, 0, sizeof(Vertex));
		Device->SetFVF(Vertex::FVF);
		Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

		Device->EndScene();
		Device->Present(0, 0, 0, 0);
	}
	return true;
}

 

 

2.過濾處理紋理

#include "d3dUtility.h"

//
// Globals
//

IDirect3DDevice9* Device = 0;

const int Width = 640;
const int Height = 480;

IDirect3DVertexBuffer9* Quad = 0;
IDirect3DTexture9* Tex = 0;


// 頂點格式
struct Vertex
{
	Vertex(){}
	Vertex(
		float x, float y, float z,
		float nx, float ny, float nz,
		float u, float v)
	{
		_x = x; _y = y; _z = z;
		_nx = nx; _ny = ny; _nz = nz;
		_u = u; _v = v;
	}

	float _x, _y, _z;
	float _nx, _ny, _nz;
	float _u, _v;

	static const DWORD FVF;
};

const DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;

//
// Framework Functions
//

bool Setup()
{


	// 建立頂點緩存
	Device->CreateVertexBuffer(
		6 * sizeof(Vertex),
		D3DUSAGE_WRITEONLY,
		Vertex::FVF,
		D3DPOOL_MANAGED,
		&Quad,
		0);

	Vertex* v;
	Quad->Lock(0, 0, (void**)&v, 0);

	v[0] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 3.0f);
	v[1] = Vertex(-1.0f,  1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f);
	v[2] = Vertex( 1.0f,  1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 3.0f, 0.0f);

	v[3] = Vertex(-1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 0.0f, 3.0f);
	v[4] = Vertex( 1.0f,  1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 3.0f, 0.0f);
	v[5] = Vertex( 1.0f, -1.0f, 1.25f, 0.0f, 0.0f, -1.0f, 3.0f, 3.0f);

	Quad->Unlock();

	//
	// Create the texture and set texture
	//

	D3DXCreateTextureFromFile(
		Device,
		"a.bmp",
		&Tex);

	Device->SetTexture(0, Tex);

	Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	Device->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

	//
	// Don't use lighting for this sample
	//

	Device->SetRenderState(D3DRS_LIGHTING, false);

	//
	// Set the projection matrix
	//

	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(
		&proj,
		D3DX_PI * 0.5f,
		(float)Width / (float)Height,
		1.0f,
		1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &proj);

	return true;
}

void Cleanup()
{
	d3d::Release<IDirect3DVertexBuffer9*>(Quad);
	d3d::Release<IDirect3DTexture9*>(Tex);
}

bool Display(float timeDelta)
{
	if (Device)
	{
		//
		// Update the scene
		//

		// set wrap address mode
		if (::GetAsyncKeyState('W') & 0x8000f)
		{
			Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
			Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
		}

		// set border color address mode
		if (::GetAsyncKeyState('B') & 0x8000f)
		{
			Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
			Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
			Device->SetSamplerState(0, D3DSAMP_BORDERCOLOR, 0x000000ff);
		}

		// set clamp address mode
		if (::GetAsyncKeyState('C') & 0x8000f)
		{
			Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
			Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
		}

		// set mirror address mode
		if (::GetAsyncKeyState('M') & 0x8000f)
		{
			Device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
			Device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
		}

		//
		// Draw the scene
		//

		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
		Device->BeginScene();

		Device->SetStreamSource(0, Quad, 0, sizeof(Vertex));
		Device->SetFVF(Vertex::FVF);
		Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 2);

		Device->EndScene();
		Device->Present(0, 0, 0, 0);

	}
	return true;
}
相關文章
相關標籤/搜索