建立mip紋理鏈

2021-09-22 12:44:36 字數 3330 閱讀 2395

(1)

我們要做的是,根據原始紋理t0建立一系列的紋理(通常使用平均濾波):t1、t2…tn,其中每個紋理的大小都是前乙個紋理的1/4,即長度和寬度減半,如圖12.40所示。

要根據前乙個mip紋理計算當前紋理中紋素的值,可以使用平均濾波器,即在rgb空間中,計算紋素(x,y)、(x+1,y)、(x+1,y+1)和(x,y+1)的平均值,然後將結果寫入到當前紋理中,如圖12.41所示。

建立mip紋理鏈時需要遵守一些規則。首先,所有紋理都必須是方形的,且邊長為2的冪。這樣,可以在兩個軸上按相同的比例縮小,mip紋理鏈末尾的最後乙個紋理總是1×1的。另乙個約定是,原始紋理為mip等級0,然後依次為mip等級1、2、3、4…n。例如,如果原始紋理的大小為256×256,則mip鏈中各個紋理的大小如表12.4所示。

表12.4 原始紋理為256×256時,各個mip紋理的大小

mip紋理

紋理大小

mip紋理

紋理大小 t0

256×256 t5

8×8 t1

128×128 t6

4×4 t2

64×64 t7

2×2 t3

32×32 t8

1×1 t4

16×16

除原始紋理外,mip等級數為log2t0的邊長。

在這個例子中,為log2256 = 8。要計算總紋理數,只需將上述結果加1。因此計算總紋理數的公式為:log2t0的邊長+1。在這個例子中,總紋理數為9。

(2)這裡紋理要占用多少記憶體呢?圖12.42是實際的mip紋理,其中每個紋理的大小都是前乙個紋理的1/4。由於每次都將紋理縮小到原來的1/4,因此占用的記憶體很少。下面計算在前乙個例子中,紋理需要占用多少記憶體。

圖12.42  實際的mip紋理

初始紋理的大小為256×256,需要占用2562個字。mip紋理鏈需要的記憶體量如下:

要計算x為原始紋理所需記憶體量的多少倍,將其除以2562:

換句話說,加上mip紋理時,每個紋理需要的記憶體量只增加33%,代價很小,收益卻很高。

圖12.43  支援mip紋理鏈的紋理指標陣列

這種方案存在的唯一問題是,我們強行將物體/多邊形的點陣圖影象指標指向了乙個位圖指標陣列。因此,必須非常小心,避免不知道紋理已被mipmap化的函式將0級紋理視為普通紋理;而知道紋理已被mipmap化的函式必須從mip紋理鏈中選擇正確的紋理。

(3)

int generate_mipmaps(bitmap_image_ptr source,    // 原始紋理  

bitmap_image_ptr *mipmaps, // 指向mip紋理陣列的指標

float gamma) // gamma修正因子

// end for y

} // end for x

} // end for mip_level

// 讓mipmaps指向指標陣列

*mipmaps = (bitmap_image_ptr)tmipmaps;

// 成功返回

return(num_mip_levels);

} // end generate_mipmaps

(4)

該函式接受三個引數,它們有些棘手。第乙個引數是點陣圖指標source,可以是指向任何有效bitmap_image物件的指標,切記它是乙個指標。第二個引數要複雜些:

bitmap_image_ptr *mipmaps; 

這是乙個指向bitmap_image指標的指標。假設物體(或多邊形)有乙個texture指標,它指向乙個bitmap_image。現在的問題是,當mip紋理函式生成所有的mip紋理時,我們要將該指標指向mip紋理鏈本身,為此,需要知道該指標的位址,以便能夠修改它,因此需要乙個** bitmap_image。這就是需要乙個指向指標的指標作為引數的原因。我們將讓該引數指向mip紋理指標陣列。

這個函式提供了這樣的靈活性:可以將同乙個物件作為引數source和mipmap。對於source引數,將其設定為指向該物件的指標;對於引數mipmaps,需要將其設定為指向該物件的指標的位址,這樣函式才能對其進行修改。假設您這樣呼叫該函式:

generate_mipmaps(obj->texture, (bitmap_image_ptr *)&obj->texture,1.01); 

其中obj的型別為object4dv2_ptr,它有乙個texture欄位,該字段是乙個指向bitmap_image的指標(bitmap_image_ptr)。仔細檢視上述呼叫可以發現:我們將該指標作為第乙個引數,同時將其位址作為第二個引數,因此對第二個引數進行修改時,將修改obj->texture指向的實際值,從而丟失它指向的原始資料。但事實上,並不會丟失任何資料,我們將把obj->texture指向的原始位圖用作mip紋理鏈中的第乙個紋理。在刪除mip紋理鏈時,我們重新將該指標指向原始位圖。圖12.44說明了整個處理過程。

回到mip紋理生成函式--它建立mip紋理鏈:為紋理指標陣列分配記憶體;然後計算下乙個mip等級的大小,為該mip等級分配記憶體,在rgb空間使用平均濾波器來建立該mip等級。這一過程不斷重複,直到mip等級的大小為1×1為止,然後函式結束。該函式的最後乙個引數(預設值為1.01)用於設定gamma值。使用平均過濾器來不斷縮小影象時,其亮度會逐漸降低;因此通常使用gamma因子來提高每個mip等級的亮度,確保所有mip等級的亮度一致。為說明這一點,作者編寫了乙個演示程式,名為demoii12_10.cpp|h。使用者可以選擇不同的紋理圖,該程式將動態地建立mip紋理,並顯示它們,如圖12.45所示。另外,使用者還可以修改gamma值,以檢視其影響。該程式的控制方式如下:

圖12.45  mip紋理實時生成程式的螢幕截圖

Unity建立紋理及紋理濾波

unity3d中建立紋理使用的是unity中的texture2d的建構函式。texture2d int width,int height texture2d int width,int height,textureformat format,bool mipmap texture2d int wid...

關於Opengl建立多個紋理

關於紋理對映 以下簡稱貼圖 在正六面體的各個表面貼圖,網上有幾種錯誤的示例,編譯沒有語法問題,但是不能被執行 1 csdn 上看到有人採用 for迴圈,逐個建立紋理,如下 char pictures for int i 0 i 6 i 遍歷位圖名稱陣列,根據位圖名稱分別生成 if textureim...

怎麼建立初始的MIP配置及模板檔案

下面我們再結合具體 給大家介紹建立mip初始的配置檔案以及模板檔案的方法。這裡我們已經安裝了mip,並且可以通過mip v命令查到mip的版本,如下圖。首先我們通過mkdir mip html需要建立乙個開發用的資料夾,這裡我們的資料夾名稱為mip html。然後我們可以dir出我們的資料夾目錄,如...