第三章 2D Rendering Texture Mapping (一)


Texture Mapping

正如我們早先提到的, texture 紋理, 是映射在 形狀和固體表面的數據; 一般來說, 這些數據是 顏色信息, 通過調用成為 texture mapping 紋理映射的過程, 可以將包含顏色信息的 image 圖片 map映射到到 (物體)表面. 除了顏色信息外, texture 數據還可以是 其他類型的數據, 如 用來 法向量映射normal mapping 的 法向量地圖( 表面每點的法向量), 用來控制透明度的 alpha數據...

Texture 紋理和其他類型的 游戲數據一樣, 一半在 runtime 運行時進行加載; 紋理處理 是 Direct3D的 不可缺少的 完整部分之一, 有現成的 built-in內置 函數足以讓我們 進行 紋理處理.作為處理開始, 需要一個從硬盤加載紋理文件的 加載創建函數: D3DX11CreateTextureFromFile(), 其支持大量的 流行 圖形圖像文件格式: BMP, PNG 和 DDS. D3DX11CreateTextureFromFile() 函數 有6 個參數, 原型如下:

HRESULT D3DX11CreateTextureFromFile(
    ID3D11Device     *pDevice,            // 正如在 <swapchain ,context 和 device 的區別與聯系>所說的, device 是創建對象的
    LPCTSTR         pSrcFile,             // 要加載的 紋理文件目錄
    D3DX11_IMAGE_LOAD_INFO    *pLoadInfo,    // [可選]的 image 信息結構體, 指明 該函數控制 如何進行加載 紋理文件, 例如可設置CPU相關的存取標記, 內部格式, 寬度和高度等.
    ID3DX11ThreadPump         *pPump,        // 線程相關, 用於多線程的 asynchronously異步加載
    ID3D11Resource            **ppTexture,// 加載成功后的存儲位置, 這時該參數會得到一個 ready-to-go 的紋理
    HRESULT                    *pHResult    // 呃.......
);

在 Direct3D 中, 各種函數可以加載的 image 圖片格式如下:

Windows Bitmap ( BMP)
Joint Photographic Expert Group -- i.e., JPEG ( JPG)
Portable Network Graphics ( PNG)
Tagged Image Format ( TIFF)
Graphics Interchage Format ( GIF)
DirectDraw Surface ( DDS)
Windows Media Player ( WMP)

 

Texture Interface

Texture Interface 管理 image圖像 數據, Direct3D中共有三種 類型:

> ID3D11Texture1D -- 處理 1D 或者 紋理圖像分離 ?(暫無法翻譯)

> ID3D11Texture2D -- 最常用的 紋理資源 類型

> ID3D11Texture3D -- 通量紋理?(3D 紋理)(暫無法理解翻譯)

每種 texture resource 紋理資源都包含一種或多種的 子資源; 子資源 代表着 不同的 MIP 等級, 我們會在 下一節討論. 游戲中使用的紋理 大部分是 2D類型, 需要轉變 車工 ID3D11Texure2D 資源. 圖形圖像編輯器( 例如 Adobe Photoshop) 能夠 生成創建 2D 紋理, 和 1D紋理( shader 使用的 查找表, 此時就是一個數組). 除簡單 的紋理映射外, 1D 和 3D 紋理還用在 表現 高級特殊特效使用. 

2D 紋理 采用簡單值 表示其 紋理坐標. 紋理坐標可以想成是  對 紋理圖表進行索引的 索引數組. 在此 2D 紋理使用兩個值表示 紋理坐標( texture coordinate): TU 和 TV ( 簡寫 U 和 V); 而 3D 紋理采用 三個值 ( TU , TV 和 TR ); 立體地圖( 我們將在會在 "Texture Details" 小結討論)也是用 三個紋理坐標, 因為它也只是簡單的三維通量.

 MIP Maps

紋理中的 每一個像素都是一個 texel( 紋素? 圖素? 無法翻譯); texel 在 color map 顏色地圖中就是一個 顏色值, 通常在 圖形圖像格式中的 0 到 255 范圍內. 32位的圖像 有 4個 8位組成, 分別分配成 紅色, 綠色, 藍色 和 alpha 值( 有時用來控制透明), 每種顏色各占一個字節byte, 32位包含4個字節; 這樣的話, RGB圖片, 將需要 3個字節共24位.

大部分圖形圖像編輯器使用 0到 255 表示顏色范圍, 如 Adobe Photoshop的顏色板的拾取器中的RBG顏色都固定在 0到 255 范圍內.

一張圖片的 分辨率描述 了它的 寬度和高度( 在texel角度來看); 例如一張 分辨率為1024 * 768 的圖片表示 在寬度上有 1024個 texel 高度上 768 個texel, 相當於一個 有 1024 行, 每行 768列 的表的大小; 那么1024 * 768 分辨率就共有 786,432 個texel; 如果每個 texel的大小為 4個字節 (32 位), 那這張圖片的呃大小為 786,432 * 4 = 3,145,728個字節 = 3072 kb, 即未壓縮的 3M 大小.

那么什么是 MIP map 呢? 先談 MIP level( MIP 等級? MIP階級? ), MIP levels 是 同一張紋理按照分辨率遞減的 不同版本( 的紋理); MIP levels 的存在, 可以使系統根據 要處理的surface表面的距離, 自主的選擇合適 分辨率的 紋理, (下面就是 MIP levels:), 這是出於一種考量:

(現實中也是)越是距離遠的 物體, 越是沒有辦法看清楚它的細節, 因為我們不夠近, 在進行紋理映射表面時, 也沒有必要采用高分辨率的紋理, 否則反而會影響效果, 以下圖解說, 

越是遠離我們視野的 物體, 繪制到屏幕上的像素就越少, 如果還是采用高分率去映射的話, 會導致過多的 texel 繪制在用一個位置上, 不僅浪費還會產生疊加; 同樣, 為了能夠產生高質量的顯示效果, 越是近的物體表面, 我們需要映射(貼上)高分辨率的貼圖, 以顯示更多的細節. 

這是一種很重要的機制, 越少數據進行拷貝移動, 運算越快, 游戲性能就能得到潛在性的提高; 如果很多物體遠離我們的視野, 並且采用 低一些分辨率的texture而 看起來很正常, 跟高分辨率貼上的效果 一樣的話, 為什么還要使用高分辨率的texture呢. 舉個我自己的例子來說, 我在<<Dx11DemoBase 基類(二) 初始化 DirectX11 的 4個基本步驟>>中插入了下面這張圖片, 分辨率為 2560 * 1920, 文件大小為 1.34MB, 屏幕擺放尺寸為 800 * 600, 每次當我預覽本隨筆/或者刷新頁面訪問本隨筆, 使用滾動條 快速滾到這里時, ( 我的網速是較慢的e加寬, 內存2G) 畫面會暫停, 一卡卡的, 我才這時應該在 加載 1.34 MB文件, 再變換縮小到 800 * 600 現實尺寸時 要處理 2560 * 1920 個texel; 而再快速滾動到 本隨筆最底部的 分辨率為 800 * 600, 文件大小為 126KB, 屏幕擺放大小 也為 800 * 600的 相同一張圖片時, 會加載顯示快一些, 這是因為只需要處理 800 * 600 個texel, 也能達到相同的效果( 呃, 這里所謂的效果就是指 僅僅查看這兩張示意圖, 不做放大縮小).

那么, 這個處理機制, 被稱為 mipmapping, 而 D3D11CreateTextureFeomFile() 函數默認會生成一整套的 MIP levels ; 使用 MIP map的另外一好處是減少走樣.

MIP 還引入了兩個新的概念 MIN 和 MAG. Minification 發生在 textured surface( 已映射的? 已貼圖的)表面 遠離我們的視野, 當物體遠離時, 表面變小, 更多的texel將會合並到 一個相同的屏幕像素上; 而當物體靠近我們時, 表面變大, 反過來 更多的 像素 繪制相同的一個 texel , 產生 Magnification. 而如果 一個 像素剛好 一一對應到 一個 texel上是, Minification 和 Magnification 就不會發生, 不幸的一個現實是, 在3D游戲中, 總是有各種不同尺寸的不同距離物體表面需要映射貼圖.

Texture Detail

有時候, 我們可能希望能夠獲取剛剛加載的 紋理文件 的 維度 和 像素格式, 這個需求可以 讓ID3D11Texture2D::GetDesc() 函數 返回一個 D3D11_TEXTURE2D_DESC 結構體 填充信息 取得.

D3D11_TEXTURE2D_DESC 是 描述 紋理信息的結構體中的一種特定 描述2D 紋理的結構體, Direct3D 也提供了 D3D11_TEXTURE1D_DESC 和 D3D11_TEXTURE3D_DESC 分別 描述 1D 和 3D 紋理; 但 D3D11_TEXTURE2D_DESC 提供了如下額外的 信息:

typedef struct D3D11_TEXTURE2D_DESC{
    UINT                Width;
    UINT                Height;
    UINT                MipLevels;
    UINT                ArraySize;
    DXGI_FORMAT         Format;
    DxGI_SAMPLE_DESC     SampleDesc;
    D3D11_USAGE            Usage;
    UINT                BindFlags;
    UINT                CPUAccessFlags;
    UINT                MiscFlags;
}D3D11_TEXTURE2D_DESC;

D3D11_TEXTURE2D_DESC 結構體中的每個成員都可以在 context中訪問到, 處理 ArraySize( 呃, 翻譯有些不清晰): Each of the members of the D3D11_TEXTURE2D_DESC structure has been seen in on context or another, with the exception of ArraySize. 在我們描述 ArraySize 之前, 我們先討論下 cube maps 立體地圖, 立體地圖 由 一組 2D 紋理組成, 用以產生一種 (立體)環境, 這種地圖一般 有 上,下,左,右,前 和 后 這些方向, 如下圖所示, D3D11_TEXTURE2D_DESC 的 ArraySize 將會是 6 , 表示6個立方體的面, 需要 6張圖片.

 

 

 

 

下圖是 解釋 高低分辨率對相同顯示效果物體的表面貼圖的影響低分辨率圖:


免責聲明!

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



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