Directx11教程(31) 紋理映射(1)


        在前面的例子中,我們要么是直接給頂點賦顏色值,要么是在頂點屬性中設置DiffuseSpecular系數,從而根據光照參數計算得到物體表面顏色,但這樣得到的顏色真實感要差很多。如果我們直接把一副圖像映射到三角形面上,從而得到物體表面顏色值,效果會好很多,比如下面的兩幅圖,右邊的圖是把一副圖片映射到2個三角形上。

image

 

      甚至,我們還可以直接使用圖像的顏色值做為頂點(或者pixel)的diffuse值,融合光照計算公式,得到最終的表面顏色值,這樣會有更好的效果。

     通常,我們把圖像映射到三角形面上的技術稱作紋理映射(texture mapping)。在紋理映射過程中,我們使用紋理坐標的方式(或稱u、v坐標),把紋理進行划分,如下圖,假設圖像為256*256像素,則左上角紋理坐標為(0,0),右上角為(1,0),左下角為(0,1),右下角為(1,1)。

    之所以使用這種歸一化的uv坐標,主要是要使得uv坐標值和紋理圖像大小沒有關系,比如對下面的圖,uv坐標(0.5, 0.5),其實就是映射到紋理上的像素(128,128),如果換成一個更大的紋理圖像(1024*1024),則(0.5,0.5)就映射到(512,512)。

image

     對於一個三角形,我們要為每一個頂點指定uv坐標,如下圖的2個三角形,我們按照圖上標的紋理坐標指定uv坐標,則左邊的2個三角形則會被完整的映射成右邊的紋理形狀。

image

下面了解幾個和紋理采樣有關的概念:

Magnification與Minification:

    如果光柵化后的三角形正好是256*256像素,這和紋理的大小正好相等,那么映射關系就是一個像素對應紋理的一個單元(texel),但實際情況可能更復雜。

    比如:紋理大小為256*256,但我們的兩個三角形組成的quad卻是512*512,則一個紋理單元要對應quad上的四個像素,一個紋理單元對應多個光柵化后的像素的情況通常稱作Magnification,

image

    

     在magnification情況下如何進行紋理映射呢?通常是用雙線性插值的方式,比如下面左邊的圖中紅色的pixel,沒有對應的紋理texel,則它的顏色值用它的上下左右的pixel顏色插值得到,當然我們也可以選擇最接近的紋理單元顏色做為其顏色,具體要視紋理濾波中設置的MAG值。

image

     和magnification的情況相反,minification表示三角形面小,而紋理大的情況,就是一個pixel如何在多個紋理單元中選擇顏色的問題。這時可以選擇最接近的紋理單元,也可以把上下左右紋理單元進行雙線性插值,再和pixel映射起來。比如下圖128*128的quad面和256*256紋理映射的情況:

image

mipmap層:

      通常,我們創建紋理的時候,可以選擇創建mipmp層,這時,系統就自動會為我們創建一系列下采樣的圖像,每個圖像都是前面一個圖像的1/4(如下圖所示),我們可以自己選擇mipmap的層數。如果使用dds文件的話,其中已經包含了mipmap層,所以最好把自己需要的紋理轉化成dds格式,預處理得到需要mipmap層數。

image

 

      在使用mipmap層的情況下,如何做紋理映射呢?

     比如紋理原始大小是256*256,我們的三角形是178*178,那么這時會做三線性插值,四邊形先和128*128紋理執行magnificaiton插值得到一個結果,再和256*256紋理做minification插值得到一個結果,最后再對這2個結果進行線性插值,得到的顏色為最終的pixel顏色。

image

紋理的尋址模式:

     通常我們頂點的紋理坐標在[0,1]范圍內,這樣光柵化后的三角形pixel總能從紋理中找到對應的紋理單元。

    我們也可以通過設置紋理尋址模式,來擴展紋理映射,對於不在[0,1]之間的紋理坐標,也可以找到對應的紋理單元。

通常的紋理尋址模式包括:

wrap方式:

     對於不在[0,1]之間的紋理坐標,采用纏繞的方式來對應紋理單元,比如下面圖所示,這樣的方式特別適合用小紋理來貼一個大的平面,比如在地面鋪瓷磚,在地面上鋪草地等等。這也要求我們設計紋理圖片時,把左右、上下的邊緣部分,最好能無縫的連接起來。

image

border方式:

    把不在[0,1]范圍的紋理坐標設置為一些指定的顏色,比如下圖,指定為紅色

image

Clamp方式:

     把不在[0,1]范圍的紋理坐標指定為離其最近的紋理單元顏色。

image

Mirror方式:

     就是把不在[0,1]范圍的紋理坐標按鏡像的方式指定紋理單元,如下圖所示:

image

現在我們了解一些紋理采樣的設置,在D3D11中使用紋理前我們必須設定采樣狀態,主要就是通過下面的的函數:

// 創建紋理采樣狀態描述符.
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
samplerDesc.MipLODBias = 0.0f;
samplerDesc.MaxAnisotropy = 1;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
samplerDesc.BorderColor[0] = 0;
samplerDesc.BorderColor[1] = 0;
samplerDesc.BorderColor[2] = 0;
samplerDesc.BorderColor[3] = 0;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;

// 創建紋理狀態.
result = device->CreateSamplerState(&samplerDesc, &m_sampleState);
if(FAILED(result))
{
    return false;
}

本篇教程中,我們了解D3D11紋理使用中的一些基本概念,下一篇日志,要開始寫代碼了…


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM