OpenGL之紋理映射使用mipmap

OpenGL之紋理映射使用mipmap

紋理繪畫多邊形當遠離視點,會出現視覺失真或炫目問題,原因是OpenGL對兩個相鄰的像素進行采樣時,從紋理圖中的一些差別較大的部分進行采樣所產生的,在靜止場景問題並不明顯,若運動時紋理紋理采樣發生改變時炫目問題將會更特出,使用mipmap『紋理鏈』能消除部分失真,因為低解釋度的紋理被應用到遠距離的多邊形上時采樣更加精准.因為紋理一級級縮小時紋理可以保持平滑,使用mipmap『紋理鏈』的另一個好處是較小的紋理更容易保存在顯卡『記憶體』中提高命中率.

OpenGL的gluBuild2DMipmaps()可以全自動的生成mipmap『紋理鏈』.但不仿自已動手生成.

mipmap『紋理鏈』演示程式下載:

  1. 按M鍵可切換『紋理鏈』啟用與禁用,當啟用時炫目失真將大副減小.
  2. 按ESC鍵相機返回原點.
  3. 按方向鍵移動相機

紋理結構定義可梯『OpenGL之紋理映射』OpenGL根據目標圖像的大小選擇紋理圖像,『紋理鏈』索引從0開始到分辨率1*1 結束,所以你要對紋理近行縮小:

 

生成紋理鏈代碼

1.不斷縮小紋理圖,直到分辨率1*1

while (width != 1 && height != 1){

2.獲取索引

index = texture->count;

3.縮小紋理

texture->image[index] = Decrease_Image_Texture(texture->image[index-1], width, height);

4.紋理個數加一

++texture->count;

5.寬與高減一半

width = width / 2;

height = height / 2;

}

紋理圖像的寬和高均縮小一半的函式

image:紋理圖

width,height:寬和高

PBYTE Decrease_Image_Texture(PBYTE image,int width,int height){

int r1,r2,r3,r4, g1,g2,g3,g4, b1,b2,b3,b4 ;

int index,x,y;

//分配縮小紋理記憶體

buffer = (PBYTE)malloc(width/2 * height/2 * 3);

for (y = 0; y < height; y = y + 2) //遍歷Y座標

{

for (x = 0; x < width; x = x + 2)//遍歷X座標

{

index = Get_Index_Texture(x, y, 0, 0, width, height) * 3;// 提取紋理像素

r1 = image[index + 0];

g1 = image[index + 1];

b1 = image[index + 2];

index = Get_Index_Texture(x, y, 1, 0, width, height) * 3;// 提取紋理像素

r2 = image[index + 0];

g2 = image[index + 1];

b2 = image[index + 2];

index = Get_Index_Texture(x, y, 0, 1, width, height) * 3;// 提取紋理像素

r3 = image[index + 0];

g3 = image[index + 1];

b3 = image[index + 2];

index = Get_Index_Texture(x, y, 1, 1, width, height) * 3; //提取紋理像素

r4 = image[index + 0];

g4 = image[index + 1];

b4 = image[index + 2];

index = (y/2 * width/2 + x/2) * 3;

//加權平均計算目標紋理像素

buffer[index + 0] = (r1 + r2 + r3 + r4) / 4;

buffer[index + 1] = (g1 + g2 + g3 + g4) / 4;

buffer[index + 2] = (b1 + b2 + b3 + b4) / 4;

}

}

 

計算紋理像素索引函式

x,y:座標

dx,dy:座標增量

wdith,height:紋理圖的寬和高

int Get_Index_Texture(int x, int y, int dx, int dy, int width, int height) {

if (x + dx >= width) //判斷x座標是否越界

dx = 0;

if (y + dy >= height) //判斷y座標是否越界

dy = 0;

int index = (y + dy) * width + (x + dx);        計算紋理像素索引

return index;           返回索引

}

 

綁定mipmap『紋理鏈』代碼函式

bool Bind_Texture(TEXTURE_PTR texture){

glGenTextures(1, &texture->ID);//生成紋理

glBindTexture(GL_TEXTURE_2D, texture->ID);//綁定紋理

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);// 重複紋理

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);// 重複紋理

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);//放大紋理像素採樣線性插值(加權平均)

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);//縮小紋理紋理鏈採樣使用NEAREST,過濾使用LINEAR

for (int index = 0, v = 1; index < texture->count; ++index, v = v * 2)//遍歷紋理鏈

glTexImage2D(GL_TEXTURE_2D, index, GL_RGB, texture->width / v, texture->height / v, 0, GL_RGB, GL_UNSIGNED_BYTE, texture->image[index]);    //載入紋理

}

 

評論