DirectX SDK 2006學習筆記4——紋理

Copyright © MikeFeng  QQ: 76848502 

  紋理在D3D中是一個非常重要的概念,它的出現改變了以前3D物體表面不真實的狀況,爲程序員提供了將2維圖像應用到3維物體上去的功能。請做好心理準備,因爲新的概念將像暴風驟雨般的襲來,而在沒有弄懂基本概念之前是不可能進行下一步的學習的。下面是一些術語的大致概念:
  • 紋理( Textrue ):將要應用到3維(或者2維)模型中的圖片,可以有dds, hdr, bmp, tga, jpg, png等多種格式,各種格式可以有8位,16位,32位,64位以及128位的色彩位深
  • 紋理座標( Textrue Coordinates ):x,y軸分別以[0,1]爲區間的2維座標。將紋理的長和寬分別認作單位1,用u和v來表示紋理上的每一個色彩的座標。
  • 圖素( Texel ):紋理上每一個色彩點稱爲圖素。每個圖素都有自己的紋理座標。
  • 紋理尋址模式( Textrue Addressing Modes ):系統映射[0, 1] 區間以外的圖素座標的模式。紋理尋址模式共有五種,它們分別是包裝紋理尋址模式、鏡像紋理尋址模式、夾持紋理尋址模式,邊框紋理尋址模式和一次鏡像紋理尋址模式。

                包裝紋理尋址模式:D3D默認尋址模式。效果如下:

                鏡像紋理尋址模式:每兩個相鄰的單位紋理都是鏡像效果的。如下:

                夾持紋理尋址模式:只映射在區間[0, 1]中的紋理,然後在其他空間中塗上和紋理邊界相反的顏色,如圖:

                邊框顏色紋理尋址模式:在區間[0, 1]之外塗上指定顏色,例如:

                一次鏡像紋理尋址模式:紋理在[-1.0, 1.0]範圍內作鏡像,在該範圍外作夾持。

  • 紋理包裝:決定如何在紋理座標之間做插值計算。
  • 紋理過濾:通過給定的uv座標從紋理貼圖中獲得圖素的一種方法。爲了抗鋸齒,D3D中採用了3中技術來實現紋理過濾,它們分別是最近點採樣,線性紋理過濾,各向異性(anisotropic)紋理過濾。而現在遊戲中看到的圖像高級選項中,一般都有點採樣、雙線過濾(即D3D的線性紋理過濾),三線過濾(即D3D中的線性過濾加上mipmap),以及各向異性過濾。

                mipmap:由一系列紋理組成,其中每張紋理的高寬都是前一級高寬的一半。D3D在渲染時會自動挑選出一個圖素與像素的比值最接近於1的mip層級。

                最近點採樣:將紋理座標對齊到最接近的整數,再將那個位於整數座標上的紋理像素作爲最終的顏色。缺點:容易在圖像邊界上造成錯誤,優點:快。

                線性紋理過濾:(即雙線紋理過濾),計算相對於採樣點最近的4各圖素(上下左右4個點)的平均值。缺點:有各項異性失真可能。

                三線過濾:對於每個像素,三線過濾會先選擇兩張最接近的mipmap,將它們雙線過濾爲兩張理想大小的mipmap,然後根據理想的mip級組合這兩張過濾後的mipmap中的對應像素。缺點:有各項異性失真可能。

                各項異性過濾:根據屏幕像素的伸張度來測量各項異性,再將屏幕像素反向映射到紋理空間中。效果:在非水平的渲染時要比三線過濾更加銳化。

  • 抗鋸齒:有全屏多采樣和可屏蔽多采樣之分。全屏多采樣對每個像素進行多次採樣,這些不同的樣本被混合後輸出到屏幕。可屏蔽多采樣僅影響三角形和三角形組,不影響直線。
  • Alpha混合:可將圖元顏色和先前的幀緩衝器像素的顏色組合起來,用於實現透明效果。有個很著名的alpha混合計算公式:

      FinalColor = SourceColor * SourceBlendFactor + DestColor * DestBlendFactor

      如果使SourceBlendFactor + DestBlendFactor = 1,那麼就可以實現透明效果。

 
 

Example 1           Simple Texture & Wrap Texture Address Mode

  一個簡單的貼圖是很容易實現的,因爲它可以簡單的建立FVF基礎之上,整個過程是這樣的:在頂點緩衝之中添加紋理座標信息,然後在OnCreateDevice中添加紋理創建代碼,在OnFrameRender中添加紋理的設置,最後在OnDestoryDevice中添加紋理資源釋放代碼。
 
定義:在頂點緩衝定義中添加紋理座標信息
LPDIRECT3DTEXTURE9              g_pTexture      = NULL;        // Texture
structCUSTOMVERTEX
{
        FLOATx, y, z, rhw; // The transformed position for the vertex
        //DWORD color;        // The vertex color, no use here
        FLOATtu, tv;           // The texture coordinates
};
#defineD3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_TEX1)
 
OnCreateDevice:添加紋理創建代碼,在頂點緩衝中添加紋理座標信息,橫向複製兩遍紋理
V_RETURN( D3DXCreateTextureFromFile(pd3dDevice, L"DaNing_Hudie.jpg", &g_pTexture) );
CUSTOMVERTEXvertices[] =
{
        {   0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,}, // x, y, z, rhw, color
        {   (float)pBackBufferSurfaceDesc->Width, 0.0f, 0.5f, 1.0f, 2.0f, 0.0f,},
        {   (float)pBackBufferSurfaceDesc->Width, (float)pBackBufferSurfaceDesc->Height, 0.5f, 1.0f, 2.0f, 1.0f,},
        {   0.0f, (float)pBackBufferSurfaceDesc->Height, 0.5f, 1.0f, 0.0f, 1.0f, },
};
 
OnFrameRender:在BeginScene和EndScene中間添加如下代碼。因爲D3D默認使用包裝紋理尋址模式,所以不必調用SetSampleState來設置紋理模式。
pd3dDevice->SetTexture( 0, g_pTexture );
 
OnDestroyDevice:添加釋放代碼
SAFE_RELEASE( g_pTexture);
 
 
Example 2           Texture Address Mode 
包裝尋址模式見Example 1。接下來是鏡像尋址模式。
頂點緩衝的初始化:橫向複製四遍,縱向複製兩遍,一共是八個紋理單元
CUSTOMVERTEXvertices[] =
{
        {   0.0f, 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,}, // x, y, z, rhw, color
        {   (float)pBackBufferSurfaceDesc->Width, 0.0f, 0.5f, 1.0f, 4.0f, 0.0f,},
        {   (float)pBackBufferSurfaceDesc->Width, (float)pBackBufferSurfaceDesc->Height, 0.5f, 1.0f, 4.0f, 2.0f,},
        {   0.0f, (float)pBackBufferSurfaceDesc->Height, 0.5f, 1.0f, 0.0f, 2.0f, },
};
OnFrameRender:添加在u方向和v方向的鏡像紋理尋址模式代碼
pd3dDevice->SetTexture( 0, g_pTexture );
pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR );
pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR );
 
其餘函數和Example 1相同。效果如下:
 
類似的夾持紋理尋址模式效果圖
 
邊框顏色紋理尋址模式需要再加一個SetSampleState
pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER );
pd3dDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER );
pd3dDevice->SetSamplerState( 0, D3DSAMP_BORDERCOLOR, 0xff88aa66 );
一次鏡像紋理尋址模式效果,範圍之外填黑色,並不是想象中的夾持@.@
 
 
Example 3           Texture Wrapping
v方向上的紋理包裝,在OnFrameRender添加
pd3dDevice->SetRenderState( D3DRS_WRAP0, D3DWRAP_V );
其餘函數和Example 2類似
u方向上的代碼類似,效果圖略
 
 
Example 4           Texture Filter 
MipMap
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章