日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

纹理映射技术

發(fā)布時間:2025/5/22 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 纹理映射技术 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

第六集 紋理映射技術(shù)

?

為使建立的3D模型更接近現(xiàn)實世界中的物體, 簡單的顏色變換已經(jīng)無能為力, 這時我們就需要紋理映射技術(shù)了.

?

??? 這一集我們講解基礎(chǔ)的紋理映射技術(shù)的數(shù)學模型, 對于在粒子系統(tǒng)使用的過程紋理技術(shù)在高級部分講解.

?

6.1 二維紋理映射

?

6.1.1 紋理映射的簡單建模

?

??? 二維紋理映射就是從二維紋理平面到三維物體表面的映射. 一般二維紋理平面是有范圍限制的, 在這個平面區(qū)域內(nèi), 每點都可用數(shù)學函數(shù)表達, 從而可以離散的分離出每點的灰度值和顏色值, 這個平面區(qū)域稱為紋理空間, 一般將紋理空間的平面區(qū)域定義在[0, 1] * [0, 1].

?

??? 紋理映射是確定物體表面一點P在紋理空間中的對應點(u, v), 從而紋理空間中的點(u, v)處的紋理值就是物體表面點P的紋理屬性. 這樣屏幕上顯示的像素的顏色可通過下面的映射得到,

F : Screen Space --> Object Space

?G : Object Space --> Texture Space

其中F我們在第二集中已詳細講解過, 所以我們關(guān)心的是G. 只要確定了物體表面的紋理屬性, 接著就是將物體表面上各點所對應的紋理值作為光照明模型中的相應參數(shù)進行光強度計算, 再繪制畫面.

?

??? 所以G函數(shù)的定義直接影響畫面的效果, 如何確定G非常重要. G可表示為,

(u, v) = H(x, y, z)

?

其中(u, v)和(x, y, z)分別是紋理空間和物體空間中的點. 現(xiàn)在從簡單的圓柱開始, 一個高h, 半徑為r的圓柱的紋理映射方法, 我們用參數(shù)形式表示圓柱,

?

x = r * cos a

y = r * sin a

z = h b

0 <= a <= 2PI, 0<= b <= 1

?

從紋理空間 [0, 1] * [0, 1] 到 [0, 2PI] * [0, 1] 的線性變換為,

u = a / 2PI

v = b

?

這樣, 我們建立了物體空間到紋理空間映射的表達式. 如圖6.1

圖6.1

?

??? 物體表面沒有象圓柱一樣, 所以上面的方法不實用.

?

6.1.2 兩步法紋理映射

?

??? 1986年, Bier和Sloan提出了一種獨立于物體表面的紋理影射技術(shù), 將紋理空間到物體空間的映射分為兩個簡單的映射復合. 兩步法紋理映射的核心是引進一個包圍物體的中介三維曲面作為中間映射媒體, 主要過程分兩步,

?

(a). 將二維紋理映射到一個簡單的三維物體表面, 如平面, 球面,圓柱面, 立方體表面, 采用不同的中間映射媒體生成的紋理效果是不同的, 要根據(jù)目標物體表面來選擇.

?

???? S : (u, v) --> (x', y', z')?? ---??? S-映射

?

???? 如半徑為R的球的S-映射為,

?

x = R * cos a * sin b

y = R * sin a * sin b

z = R * cos b

(0 <= a <= 2PI,?0<= b <= PI)

?

(b). 將(a)的三維物體表面上的紋理映射到目標物體表面,

?

????O : (x', y', z') --> (x, y, z)??? ---???O-映射

?

???? O-映射一般有4種, 如圖6.2,

圖6.2

????(1). 取視線在物體表面可見點(x, y, z)處的反射與

????????? 中間映射媒體表面上的交點(x', y', z')作為

????????? (x, y, z)的映射點.

?

????(2). 取物體表面可見點(x, y, z)處的法線與中間映射

?????? ?? 媒體表面上的交點作為映射點.

?

????(3). 取物體中心到可見點(x, y, z)的射線與中間映射

????????? 媒體表面上的交點作為映射點.

?

????(4). 中間映射媒體表面上的點(x', y', z')處的法線

????????? 與物體表面的交點為(x, y, z), (x', y', z')

????????? 為(x, y, z)的映射點.

?

???其中(1)映射方式應用的最廣, 稱為環(huán)境映射, 我們下一節(jié)會簡單的說明一下. 其余的三種O-映射和上面4種S-映射有12種組成, 其中可用的為5種, 如下表.

?

?

三種O-映射和4種S-映射有12種組成

_____________________________________________________________

|????/???????? |?????????|????????? |????????? |?????????|

|????? / S-映射 |?? 平面?? |? 圓柱面? |? 立方體? |??球面?? |

|O-映射/?????? |?????????|????????? |????????? |?????????|

|---------------|----------|----------|----------|----------|

| ?表面法向(2)?|?? 冗余?? |? 不適合? | 不太適合 | 不太適合 |

|---------------|----------|----------|----------|----------|

|? 物體中心(3)? |?? 冗余?? |? 不適合? |?? 適合??|?? 適合?? |

|---------------|----------|----------|----------|----------|

| 中介面法向(4) |??適合?? |?? 適合?? |?? 適合?? |?? 冗余??|

+---------------+----------+----------+----------+----------+

?

6.1.3 環(huán)境映射

?

???環(huán)境映射是兩步法紋理映射的特例, 環(huán)境映射是近似的模擬光線跟蹤, 但沒有光線跟蹤那么復雜, 所以能大大提高光線跟蹤算法的效率, 目前在商業(yè)應用中廣泛使用的紋理影射技術(shù). 環(huán)境映射的過程如圖6.3,

圖6.3

(1). 物體被中介曲面球包圍, 中介曲面球記錄了物體表面的紋理值.

(2). 視點的光線經(jīng)過一像素的四個角點投射到物體表面, 經(jīng)物體表面的反射到達中介曲面球, 圖6.3中P的紋理屬性就由中介曲面球上的E點唯一確定.

(3). 中介曲面球的缺點是在球的兩極點紋理變化太快, 形成紋理的突變.

?

???為避免中介曲面球的極點紋理突變,環(huán)境映射中可采用立方體表面為中介表面, 整個環(huán)境紋理映射由六幅圖(mip-map表)組成, 六幅圖象是六個90度視域方向拍攝的或繪制的真實景物圖象, 其映射過程簡單的將入射光線束通過物體表面片投射到立方體上, 入射光線束形成的錐和立方體表面的交集就是該物體表面片的紋理, 如圖6.4.

圖6.4

???立方體環(huán)境映射計算量比球面環(huán)境映射大很多, 主要因為光線和立方體表面的交集區(qū)域計算復雜. 為次可以以立方體中心為投影中心, 將立方體表面包含的紋理屬性投影到立方體的外接球面上, 再由球面環(huán)境映射來確定物體表面紋理, 這樣既省計算時間, 又可避免球面環(huán)境映射在極點的紋理突變.

?

6.2 特殊紋理映射

?

???這節(jié)的例子以后給出.

?

6.2.1 凹凸紋理映射

?

???兩步法紋理映射方法只能實現(xiàn)物體表面的顏色(花紋)紋理, 但不能實現(xiàn)物體表面幾何形狀的凹凸不平而形成的粗糙質(zhì)感. 為此, 出現(xiàn)了無須修改物體模型就能實現(xiàn)物體表面凹凸不平效果的紋理技術(shù) -- 凹凸紋理映射(Bump mapping).

?

???由于物體表面的光強度是由物體表面的法向量決定的, 凹凸紋理映射通過對物體表面各采樣點的法向量作微小的調(diào)整來改變物體表面的光強度, 達到凹凸不平效果.

?

???但不是任何調(diào)整都能產(chǎn)生凹凸不平的真實感效果, 我們需要建立數(shù)學模型, 定義物體表面參數(shù)方程, 在(m, n)點的法向量為,

?

V =V(m, n)

?

設(shè)Vm,Vn分別是V在m, n上的分量, 那么在(m, n)點的單位法向為,

?

N =N(m, n) = Vm X Vn / | Vm XVn |

?

現(xiàn)在用一個微小調(diào)整的函數(shù)P(m, n),?一般這個函數(shù)是連續(xù)可微的, 那么通過函數(shù)P(m, n)調(diào)整的點(m, n)的新法向量為,

?

???????????????????????????????????| V'm? = Vm + PmN

V'(m, n) =V(m, n) + P(m, n) N?? = |

???????????????????????????????????| V'n? = Vn + PnN

?

從而得到新的單位法向, 如圖6.5

N' =V'm X V'n = N + D

D= PmA - Pn B

A= N XVn,?? B = N XVm

?

圖6.5

???對于函數(shù)P(m, n), 可以用一張凹凸圖來離散的給出各點的值.

?

6.2.2 位移紋理映射(Displacement mapping)

?

???凹凸紋理映射能很好的模擬面的凹凸不平的真實感效果, 但在物體的輪廓線上的凹凸不平效果無法表達, 如圖6.6

圖6.6

我們將含有凹凸信息的面按一定方向旋轉(zhuǎn)后, 原來的凹凸不平的真實感效果就不明顯了.為此出現(xiàn)了位移紋理映射技術(shù), 它和凹凸紋理映射技術(shù)相似, 只是位移紋理映射是沿法向方向調(diào)整的是采樣點的位置, 將凹凸信息的顯示用點坐標的調(diào)整來得到, 如圖6.7

圖6.7

當含有凹凸信息的面轉(zhuǎn)過90度后, 我們還是能看出面的凹凸信息.

?

???值得注意的是, 位移紋理映射對物體表面的造型進行了改變, 所以呈現(xiàn)的凹凸信息能實現(xiàn)陰影效果.

?

6.3 紋理映射中的反走樣

?

???紋理映射常常需要將紋理圖案映射到不同大小的物體表面, 理想的是物體表面大小和紋理圖案大小一致. 但實際物體表面大于或小于紋理圖案的情況多, 這時必須取這區(qū)域的紋理屬性值--如像素顏色的平均值作為對應表面的紋理屬性, 但當物體表面形狀復雜時, 計算平均值并不能精確得到物體表面的紋理屬性.

?

???另外將一張黑白的世界象棋圖映射到物體表面, 當物體表面小到接近單位像素時, 表面只能顯示黑色或白色, 當物體位移或旋轉(zhuǎn)時, 會出現(xiàn)黑白閃爍現(xiàn)象.

?

???上面都是紋理映射的走樣問題, 相應的就有反走樣技術(shù), 我們講解mip-map技術(shù).

?

6.3.1 mip-map

?

???mip是拉丁文multum in parvo(聚集在一塊小區(qū)域內(nèi)的許多東西)的縮寫, mip-map技術(shù)根據(jù)初始的紋理圖案每邊的分辨率S, 形成一個四棱錐型的mip-map, 如圖6.8

圖6.8

圖左邊是四棱錐型的mip-map, 其中紋理圖案的層數(shù)是[log2S] + 1, 也就是設(shè)置一張64X64的紋理圖案, mip-map就以64X64為底的四棱錐, 一共有[log264] + 1 = 7層, 最上層為一個像素, 同時我們也知道為何紋理圖案都建議是2的冪次的原因.

?

???mip-map的存儲是以一張查找表的形式存儲的, 如圖6.8的右邊, 一張64X64的紋理圖案的查找表的大小是128X128. 存儲時先提取紋理圖案中每像素的R, G, B值, 然后對R, G, B值逐級壓縮來得到.

?

???mip-map在確定屏幕上可見表面的紋理過程如下,

(1). 計算屏幕上可見表面的中心在紋理空間上的映射點坐標(u, v).

(2). 確定紋理空間中以(u, v)為中心, 邊長為d的正方形, 要求正方形能覆蓋表面在紋理空間中映射的區(qū)域.(實際這樣算d太復雜, 一般d為表面在紋理空間中映射的區(qū)域的最大邊長)

(3). 根據(jù)d的大小確定使用哪一級的紋理map.

因為mip-map中的紋理圖案存儲的是特定的圖案, 即只有邊長d = 2^k, k = 0, 1, ..., [log2S]的圖案, 對于在2^k < d < 2^(k + 1)的邊長d, mip-map通過線性插值第k層的紋理和第k + 1層的紋理得到.

?

6.4 紋理映射的例子

?

6.4.1 代碼更新

?

???這集的例子是game4 project.

?

我們在這例子里改變了頂點的屬性, 加了頂點的紋理屬性, 紋理屬性是確定頂點在紋理空間中的映射點的坐標的.

?

我們在確定頂點在世界中的坐標的同時, 還要確定頂點對應的紋理空間中的坐標. 一般紋理空間中的坐標都在[0, 1]之間的, 例子中可以該成[0, 2]或[0, 4]之間, 看看物體的紋理又會如何.

?

---------------------------------------------------------------

// gamedef.h中改了頂點的屬性

#define D3DFVF_MYVERTEXTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)

?

struct MYVERTEXTEX

{

?? FLOAT x, y, z;

?? DWORD colour;

?? FLOAT tu, tv;

};

?

// d9texobject.cpp,加入load texture file的函數(shù)

HRESULT CD9TexObject::SetTexture(LPCTSTR pName)

{

?? if (m_bInit)

?? {

??????? return D3DXCreateTextureFromFile(m_pD3DDev, pName, &m_pD3DTexture);

?? }

?? return E_FAIL;

}

// d9texobject.cpp,確定頂點在世界中的坐標的同時,

// 確定頂點在紋理空間中映射點的坐標,

// 我們只是簡單將紋理圖案映射在四邊形的表面上

HRESULT CD9TexObject::UpdateD3DVertex()

{

??? LPVOID pV = NULL;

??? UINT nSize = 18 * sizeof(MYVERTEXTEX);

??? MYVERTEXTEX aVertex[] =

??? {

??????? {m_fx - m_fW, m_fy + m_fH, m_fz - m_fD, D3DCOLOR_XRGB(0, 0, 255), 0.0f, 1.0f },

??????? {m_fx - m_fW, m_fy + m_fH, m_fz + m_fD, D3DCOLOR_XRGB(255, 0, 0), 0.0f, 0.0f },

??????? {m_fx + m_fW, m_fy + m_fH, m_fz - m_fD, D3DCOLOR_XRGB(255, 0, 0), 1.0f, 1.0f },

??????? {m_fx + m_fW, m_fy + m_fH, m_fz + m_fD, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0.0f },

??????????????????????????????????????????????????????????????????????????????????

??????? {m_fx - m_fW, m_fy - m_fH, m_fz - m_fD, D3DCOLOR_XRGB(255, 0, 0), 0.0f, 1.0f },

??????? {m_fx - m_fW, m_fy + m_fH, m_fz - m_fD, D3DCOLOR_XRGB(0, 0, 255), 0.0f, 0.0f },

??? ????{m_fx + m_fW, m_fy - m_fH, m_fz - m_fD, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 1.0f },

??????? {m_fx + m_fW, m_fy + m_fH, m_fz - m_fD, D3DCOLOR_XRGB(255, 0, 0), 1.0f, 0.0f },

??????????????????????????????????????????????????????????????????????????????????

??????? {m_fx + m_fW, m_fy - m_fH, m_fz + m_fD, D3DCOLOR_XRGB(0, 0, 255), 0.0f, 1.0f },

??????? {m_fx + m_fW, m_fy + m_fH, m_fz + m_fD, D3DCOLOR_XRGB(0, 255, 0), 0.0f, 0.0f },

??????????????????????????????????????????????????????????????????????????????????

??????? {m_fx - m_fW, m_fy - m_fH, m_fz + m_fD, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 1.0f },?

??????? {m_fx - m_fW, m_fy + m_fH, m_fz + m_fD, D3DCOLOR_XRGB(255, 0, 0), 1.0f, 0.0f },

??????????????????????????????????????????????????????????????????????????????????

??????? {m_fx - m_fW, m_fy - m_fH, m_fz - m_fD, D3DCOLOR_XRGB(255, 0, 0), 0.0f, 1.0f },

??????? {m_fx - m_fW, m_fy + m_fH, m_fz - m_fD, D3DCOLOR_XRGB(0, 0, 255), 0.0f, 0.0f },

??????? ??????????????????????????????????????????????????????????????????????????

??????? {m_fx + m_fW, m_fy - m_fH, m_fz - m_fD, D3DCOLOR_XRGB(0, 255, 0), 0.0f, 1.0f },?

??????? {m_fx + m_fW, m_fy - m_fH, m_fz + m_fD, D3DCOLOR_XRGB(0, 0, 255), 0.0f, 0.0f },

??????? {m_fx - m_fW, m_fy - m_fH, m_fz - m_fD, D3DCOLOR_XRGB(255, 0, 0), 1.0f, 1.0f },

??????? {m_fx - m_fW, m_fy - m_fH, m_fz + m_fD, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0.0f }

??

??? };

??? if(FAILED(m_pD3DVBuffer->Lock(0, nSize, &pV, 0)))

??? {

??????? return E_FAIL;

??? }

?? MoveMemory(pV, aVertex, nSize);

??? m_pD3DVBuffer->Unlock();

?? return S_OK;

}

?

// d9texobject.cpp,渲染時設(shè)置物體紋理

VOID CD9TexObject::Render()

{

?? if (m_bInit)

?? {

??????? m_pD3DDev->SetStreamSource(0, m_pD3DVBuffer, 0, sizeof(MYVERTEXTEX));

??????? m_pD3DDev->SetFVF(D3DFVF_MYVERTEXTEX);

??????? if (m_pD3DTexture != NULL)

??????? {

?

????????????m_pD3DDev->SetTexture(0, m_pD3DTexture);

????????????m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);

??????? }

??????? else

??????? {

????????????m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);

??????? }

??????? m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0,? 2);

??????? m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4,? 8);

??????? m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 14, 2);

?? }

}

?

6.4.2 說明

?

6.4.2.1 函數(shù)

?

??? 一般紋理文件是單獨的存放的, 這是要創(chuàng)建紋理用到了

HRESULT D3DXCreateTextureFromFile(LPDIRECT3DDEVICE9 pDevice,

?????????????????????????????????LPCTSTR pSrcFile,

?????????????????????????????????LPDIRECT3DTEXTURE9 * ppTexture);

函數(shù)從單獨的紋理文件中創(chuàng)建紋理, 用這函數(shù)的好處是隨時可改紋理文件但不用編譯代碼. 如果為提高速度, 可以將紋理加入可執(zhí)行文件中作為資源, 這是使用

HRESULT D3DXCreateTextureFromResource(LPDIRECT3DDEVICE9 pDevice,

?????????????????????????????????????HMODULE hSrcModule,

?????????????????????????????????????LPCTSTR pSrcResource,

?????????????????????????????????????LPDIRECT3DTEXTURE9 * ppTexture);

?

??? 在渲染時, 要告訴IDirect3DDevice9物體的紋理, 使用

HRESULT SetTexture(DWORD Sampler,

??????????????????IDirect3DBaseTexture9 * pTexture);

現(xiàn)在的DirectX Graphics最多能使用8各紋理的多重紋理, 現(xiàn)在我們直用一個, 所以Sampler設(shè)為0.

6.4.2.2 紋理過濾器

?

??? 紋理到物體表面的映射需放大或縮小, 過濾器的作用就是確定紋理的縮放變化的平滑等級的. 紋理過濾器是使用IDirect3DDevice9中的SetSamplerState函數(shù)來設(shè)置的.

?

???我們將平滑等級按一般到高級列出, 同時也要注意, 平滑等級越高, 計算越耗時.

(1). 使用最近點采樣技術(shù)(這是系統(tǒng)默認值)

SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);

SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);

?

(2). 使用線性過濾技術(shù)(建議使用, 以點的2X2區(qū)域線性插值)

SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);

SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);

?

(3). 使用各向異性過濾技術(shù)

SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);

SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);

這時需要設(shè)置D3DSAMP_MAXANISOTROPY的等級,默認為1

SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 4);

?

還有D3DTEXF_PYRAMIDALQUAD和D3DTEXF_GAUSSIANQUAD過濾技術(shù).

?

6.4.2.3 mip-map設(shè)置

?

???mip-map的過濾器平滑等級和上面的相同, 也是通過SetSamplerState函數(shù)來設(shè)置. 系統(tǒng)默認是D3DTEXF_NONE, 即沒有過濾. 同時需要設(shè)置mip-map的層數(shù)

SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);

SetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, 4);

SetSamplerState(0, D3DSAMP_MAXMIPLEVEL, 4);

?

6.4.2.4 texture-address mode

?

紋理空間總是在[0, 1]之間的, 但是物體表面點映射的紋理坐標可大于1, 這時, 對于大于1的紋理映射可使用紋理重復, 鏡像, 最近點采樣, 邊界點采樣, 單次鏡像等. 通過函數(shù)SetSamplerState設(shè)置

SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);

SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);

?

可以修改例子中物體表面點映射的紋理坐標可大于1, 然后改變texture-address mode觀察物體表面紋理映射的區(qū)別.

下面的圖是使用[0, 2]的鏡像紋理技術(shù)的截圖

?

第六集 小結(jié)

?

這一集我們學習了要進行DirectX Graphics 3D編程中的二維紋理映射技術(shù), 紋理空間總是在[0, 1]之間.

總結(jié)

以上是生活随笔為你收集整理的纹理映射技术的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。