紋理映射是一種爲三角形賦予圖像數據的技術緩存
在 Direct3D 中一個紋理是經過 IDirect3DTexture9 接口來表示,一個紋理是一個像素矩陣的表面被映射到三角形上this
Direct3D 使用一個紋理座標系統,它是由水平方向的 u 軸(向右爲正)和豎直方向 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;
紋理數據能夠從存儲在磁盤中的圖片文件中讀取,放入 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提供了三種不一樣的過濾器,每種的品質級別和速度各不相同
默認的過濾方法,品質最差,速度最快
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
推薦使用,過濾產生的效果好
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
過濾產生的品質最好,處理時間最長
Device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC); Device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
若是顯卡支持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); }
#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; }
#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; }