紋理映射是一種允許我們為三角形賦予圖象數據的技術;這讓我們能夠更細膩更真實地表現我們的場景。例如,我們能夠創建一個立方體并且通過對它的每個面創建一個紋理來把它變成一個木箱(如圖6.1)。

在Direct3D中一個紋理是通過IDirect3DTexture9接口來表現的。一個紋理是一個類似像素矩陣的表面它能夠被映射到三角形上。
Direct3D使用一個紋理坐標系統,它是由用水平方向的u軸和豎直方向v軸構成。由u,v坐標決定紋理上的元素,它被叫做texel。注意v軸是向下的(如圖6.2)。

同樣,注意規格化的坐標間隔,[0,1],它被使用是因為它給Direct3D一個固定的范圍用于在不同尺寸的紋理上工作。
對每一個3D三角形,我們都希望在給它貼圖的紋理上定義一個用相應的三角形。(如圖6.3)。

我們再一次修改原來的頂點結構,添加一個用于在紋理上定位的紋理坐標。
struct
Vertex
{
float _x, _y, _z;
float _nx, _ny, _nz;
float _u, _v;
// texture coordinates
static const
DWORD FVF;
};
const
DWORD Vertex::FVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1;
|
我們在頂點格式中添加了一個D3DFVF_TEX1,它是說我們的頂點結構中包含了一個紋理坐標。
現在每個三角形都通過頂點的三個對象來建立,同時也通過紋理坐標定義了一個相應的紋理三角形。
6.2創建并賦予材質
紋理數據通常是從存儲在磁盤中的圖片文件中讀取的,且被讀進IDirect3DTexture9對象中。我們能夠使用下面的D3DX函數完成這項工作:
Creates a texture from a file.
HRESULT D3DXCreateTextureFromFile(
LPDIRECT3DDEVICE9 pDevice,
LPCTSTR pSrcFile,
LPDIRECT3DTEXTURE9 * ppTexture
);
Parameters
- pDevice
- [in] Pointer to an IDirect3DDevice9 interface,
representing the device to be associated with the texture.
- pSrcFile
- [in] Pointer to a string that specifies the
filename. If the compiler settings require Unicode, the data type LPCTSTR
resolves to LPCWSTR. Otherwise, the string data type resolves to LPCSTR. See
Remarks.
- ppTexture
- [out] Address of a pointer to an IDirect3DTexture9
interface, representing the created texture object.
Return Values
If the function succeeds, the return value is D3D_OK.
If the function fails, the return value can be one of the following:
D3DERR_NOTAVAILABLED3DERR_OUTOFVIDEOMEMORYD3DERR_INVALIDCALLD3DXERR_INVALIDDATAE_OUTOFMEMORY
Remarks
The compiler setting also determines the function
version. If Unicode is defined, the function call resolves to
D3DXCreateTextureFromFileW. Otherwise, the function call resolves to
D3DXCreateTextureFromFileA because ANSI strings are being used.
This function supports the following file formats:
.bmp, .dds, .dib, .hdr, .jpg, .pfm, .png, .ppm, and .tga. See
D3DXIMAGE_FILEFORMAT.
The function is equivalent to
D3DXCreateTextureFromFileEx(pDevice, pSrcFile, D3DX_DEFAULT, D3DX_DEFAULT,
D3DX_DEFAULT, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0,
NULL, NULL, ppTexture).
Mipmapped textures automatically have each level filled
with the loaded texture.
When loading images into mipmapped textures, some
devices are unable to go to a 1x1 image and this function will fail. If this
happens, the images need to be loaded manually.
Note that a resource created with this function will be
placed in the memory class denoted by D3DPOOL_MANAGED.
Filtering is automatically applied to a texture created
using this method. The filtering is equivalent to D3DX_FILTER_TRIANGLE |
D3DX_FILTER_DITHER in D3DX_FILTER.
For the best performance when using
D3DXCreateTextureFromFile:
- Doing image scaling and format conversion at load
time can be slow. Store images in the format and resolution they will be
used. If the target hardware requires power of two dimensions, create and
store images using power of two dimensions.
- Consider using DirectDraw surface (DDS) files.
Because DDS files can be used to represent any Direct3D 9 texture format,
they are very easy for D3DX to read. Also, they can store mipmaps, so any
mipmap-generation algorithms can be used to author the images.
這個函數能夠讀取下面圖片格式中的任意一種:BMP,DDS,DIB,JPG,PNG,TGA。
例如,用一個名為stonewall.bmp的圖片創建一個紋理,我們將按照下面的例子來寫:
IDirect3Dtexture9*
_stonewall;
D3DXCreateTextureFromFile(_device, "stonewall.bmp", &_stonewall);
|
設置當前紋理,我們使用下面的方法:
Assigns a texture to a stage for a device.
HRESULT SetTexture(
DWORD Sampler,
IDirect3DBaseTexture9 * pTexture
);
Parameters
- Sampler
Zero based sampler number. Textures are bound to
samplers; samplers define sampling state such as the filtering mode and the
address wrapping mode. Textures are referenced differently by the
programmable and the fixed function pipeline:
- Programmable shaders reference textures using
the sampler number. The number of samplers available to a programmable
shader is dependent on the shader version. .
- The fixed function pipeline on the other hand,
references textures by texture stage number. The maximum number of
samplers is determined from two caps: MaxSimultaneousTextures and
MaxTextureBlendStages of the D3DCAPS9 structure.
- [in] There are two other special cases for
stage/sampler numbers.
- A special number called D3DDMAPSAMPLER is used
for Displacement Mapping (Direct3D 9).
- A programmable vertex shader uses a special
number defined by a D3DVERTEXTEXTURESAMPLER when accessing Vertex
Textures in vs_3_0 (Direct3D 9).
- pTexture
- [in] Pointer to an IDirect3DBaseTexture9
interface, representing the texture being set.
Return Values
If the method succeeds, the return value is D3D_OK. If
the method fails, the return value can be D3DERR_INVALIDCALL.
Remarks
IDirect3DDevice9::SetTexture is not allowed if the
texture is created with a pool type of D3DPOOL_SCRATCH.
IDirect3DDevice9::SetTexture is not allowed with a pool type of
D3DPOOL_SYSTEMMEM texture unless DevCaps is set with
D3DDEVCAPS_TEXTURESYSTEMMEMORY.
例子:
Device->SetTexture(0,
_stonewall);
|
注意:在Direct3D中,你能夠設置八個紋理,它們能夠組合起來創建更多細節的圖象。這又被叫做多重紋理。
為了銷毀一個紋理,我們設置pTexture為0。例如,假如不想用一個紋理來渲染物體,那么我們就這樣寫:
Device->SetTexture(0, 0);
renderObjectWithoutTexture();
|
假如場景中有使用不同紋理的三角形,我們就必須添加與下面類似的一些代碼:
Device->SetTexture(0,
_tex0);
drawTrisUsingTex0();
Device->SetTexture(0,
_tex1);
drawTrisUsingTex1();
|
就象以前提及的,紋理被映射到屏幕中的三角形上。通常紋理三角形和屏幕三角形是不一樣大的。當紋理三角形比屏幕三角形小時,紋理三角形會被適當放大。當紋理三角形比屏幕三角形大時,紋理三角形會被適當縮小。這兩種情況,變形都將會出現。過濾(Filtering)是一種Direct3D用它來幫助這些變形變的平滑的技術。
Direct3D提供了三種不同的過濾器;每種都提供了一個不同的品質級別。越好的品質越慢,因此你必須在品質與速度之間取得一個平衡。紋理過濾器是用IDirect3DDevice9::SetSamplerState方法來設置的。
Sets the sampler state value.
HRESULT SetSamplerState(
DWORD Sampler,
D3DSAMPLERSTATETYPE Type,
DWORD Value
);
Parameters
- Sampler
- [in] The sampler stage index.
- Type
- [in] This parameter can be any member of the
D3DSAMPLERSTATETYPE enumerated type.
- Value
- [in] State value to set. The meaning of this value
is determined by the Type parameter.
Return Values
If the method succeeds, the return value is D3D_OK. If
the method fails, the return value can be D3DERR_INVALIDCALL.
- Nearest point sampling——這是默認的過濾方法且返回最差的效果,但是它的計算是最快的。下面的代碼就是設置Nearest
point sampling作為縮小放大的過濾器:
Device->SetSamplerState(0,
D3DSAMP_MAGFILTER, D3DTEXF_POINT);
Device->SetSamplerState(0,
D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
- Linear filtering——這種過濾產生還算比較好的效果,在今天的硬件上處理它還是非??斓摹K潜煌扑]使用的。下面的代碼就是設置Linear
filtering作為縮小放大的過濾器。
Device->SetSamplerState(0,
D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
Device->SetSamplerState(0,
D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
- Anisotropic filtering——這種過濾產生最好的效果,但是處理時間也是最長的。下面的代碼就是設置Anisotropic
filtering作為縮小放大的過濾器。
Device->SetSamplerState(0,
D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
Device->SetSamplerState(0,
D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
|
當使用Anisotropic
filtering時,我們必須設置D3DSAMP_MAXANISOTROPY等級,它決定處理的質量。該值越高處理的效果越好。檢查D3DCAPS9結構確認你的顯卡是否支持此功能。下面的代碼設置該值為4:
Device->SetSamplerState(0,
D3DSAMP_MAXANISOTROPY, 4);
|