紋理繪畫多邊形當遠離視點,會出現視覺失真或炫目問題,原因是OpenGL對兩個相鄰的像素進行采樣時,從紋理圖中的一些差別較大的部分進行采樣所產生的,在靜止場景問題並不明顯,若運動時紋理紋理采樣發生改變時炫目問題將會更特出,使用mipmap『紋理鏈』能消除部分失真,因為低解釋度的紋理被應用到遠距離的多邊形上時采樣更加精准.因為紋理一級級縮小時紋理可以保持平滑,使用mipmap『紋理鏈』的另一個好處是較小的紋理更容易保存在顯卡『記憶體』中提高命中率.
OpenGL的gluBuild2DMipmaps()可以全自動的生成mipmap『紋理鏈』.但不仿自已動手生成.
mipmap『紋理鏈』演示程式下載:
- 按M鍵可切換『紋理鏈』啟用與禁用,當啟用時炫目失真將大副減小.
- 按ESC鍵相機返回原點.
- 按方向鍵移動相機
紋理結構定義可梯『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]); //載入紋理
}