OpenGL之紋理映射

OpenGL之紋理映射

將紋理映射到3D模型是革命性技術,給人帶來照片般震撼逼真效果,簡單來講紋理映射就是將圖片附著於多邊形之上,這樣的圖片稱之為紋理,你可以將平鋪的地圖映射到球體上從而得到3D地球模型,下面以渲染木箱為例的演示程式:下載

生成紋理對像 簡介
void glGenTextures(GLsizei n,GLuint *textures); 生成紋理並返回紋理『索引』即ID編號
n 紋理個數
textures 數組,返回紋理ID

 

綁定紋理 簡介
void glBindTexture(GLenum target,GLuint texture); 生成紋理之後要進行綁定
Target GL_TEXTURE_1D:1維紋理

GL_TEXTURE_2D:2維紋理

Textures 紋理ID數組

 

過濾紋理 簡介
void glTexParameteri(GLenum target,GLenum pname,GLint param); 綁定之後要設定紋理過濾
target: GL_TEXTURE_1D:1維紋理

GL_TEXTURE_2D:2維紋理

pname: GL_TEXTURE_MIN_FILTER:縮小過濾

GL_TEXTURE_MAG_FILTER:放大過濾

GL_TEXTURE_WRAP_S:紋理S座標

GL_TEXTURE_WRAP_T:紋理T座標

param:

 

GL_REPEAT:重複(平鋪)紋理

GL_CLAMP:夾持紋理

GL_LINEAR:像素採樣線性插值(加權平均)

GL_NEAREST:像素採樣最接近中心紋理

GL_NEAREST_MIPMAP_NEAREST:紋理鏈採樣使用NEAREST,過濾使用NEAREST

GL_NEAREST_MIPMAP_LINEAR:紋理鏈採樣使用NEAREST,過濾使用LINEAR

GL_LINEAR_MIPMAP_NEAREST:紋理鏈採樣使用LINEAR,過濾使用NEAREST

GL_LINEAR_MIPMAP_LINEAR:紋理鏈採樣使用LINEAR,過濾使用LINEAR

 

載入紋理 簡介
void glTexImage2D(GLenum target,GLint   level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLint format,GLenum  type,const GLvoid *pixels); 設定紋理過濾後需要把紋理載入OpenGL

type:最常用GL_UNSIGNED_BYTE(無符號8Bit)

pixels:紋理數據

target: GL_TEXTURE_1D:1維紋理

GL_TEXTURE_2D:2維紋理

level: 紋理鏈索引,若只有單個紋理則設為0
internalformat: 最常用GL_RGBA或GL_RGB
width: 紋理寬度
height: 紋理高度
border: 紋理是否有變框,0沒有邊框,1有邊框
format: 最常用GL_RGBA或GL_RGB

 

紋理座標與頂點座標 簡介
void glTexCoord2f (GLfloat s, GLfloat t); 設定紋理座標(s,t), s軸紋理的x座標,t軸為紋理的y座標,紋理座標必需在頂點座標之前設定
void glVertex3f(GLfloat x,GLfloat y,GLfloat z); 設定頂點座標,並與紋理座標匹配

 

定義紋理結構 簡介
typedef struct TEXTURE_TYP{ 此結構用於保存紋理位圖信息
int   width; 紋理寬度
int   height; 紋理高度
int   bitCount; 位圖像素的bits (8BIT,16BIT,24BIT,32BIT)
int   size; 紋理數據的大小
PALETTEENTRY paletteentry; 位圖調色板
GLuint          ID; 紋理ID
PBYTE images[32]; mipmap紋理鏈
int   count; 紋理鏈個數
}TEXTURE, *TEXTURE_PTR;

 

 

紋理映射代碼示例

1.啟用深度緩衝測試,可保證多邊形被正確繪製

glEnable(GL_DEPTH_TEST);

2.啟動漸變效果

glShadeModel(GL_SMOOTH);

3.啟動多邊形隱面裁剪(消除隱藏面)如果要穿越實體則無需啟動

glEnable(GL_CULL_FACE);

4.設背面為隱面

glCullFace(GL_BACK);

5.多邊形正面使用逆時針

glFrontFace(GL_CCW);

6.啟用2D紋理映射

glEnable(GL_TEXTURE_2D);

7.載入位圖紋理(.bmp圖檔)( .tga圖檔)

TEXTURE texture;

Load_File_Texture(&texture,path);

8.生成1個紋理

glGenTextures(1, &texture->ID);

9.綁定紋理

glBindTexture(GL_TEXTURE_2D, texture->ID);

10.放大紋理像素採樣最接近中心紋理

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

11.縮小紋理過濾像素採樣最接近中心紋理

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

12.載入紋理

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture->width, texture->height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture->image[0]);

 

從指定的磁盤路徑載入紋理函式

bool Load_File_Texture(TEXTURE_PTR texture,const char * path)

{

char drive[_MAX_DRIVE] = { 0 };// 驅動器盤符

char dir[_MAX_DIR] = { 0 };    // 目錄

char fname[_MAX_FNAME] = { 0 };// 文件名

char ext[_MAX_EXT] = { 0 };    // 擴展名!

BITMAP_FILE bitmap;

TARGA_FILE  targa;

PCX         pcx;

if (texture == NULL || path == NULL)

return false;

//將路徑名分拆為組件!

_splitpath(path, drive, dir, fname, ext);

if (stricmp(ext, “.bmp”) == 0)// 載入位圖

{

Load_Bitmap(&bitmap, path);// 載入BMP文檔

Load_Bitmap_Texture(texture, &bitmap);// 載入紋理

}

else

if (stricmp(ext, “.tga”) == 0)// 載入位圖

{

Load_Targa(&targa, path); // 載入tga文檔

Load_Targa_Texture(texture, &targa);// 載入紋理

}

else

if (stricmp(ext, “.pcx”) == 0)// 載入位圖

{

Load_PCX(&pcx, path); // 載入PCX文檔

Load_PCX_Texture(texture, &pcx);// 載入紋理

}

return false;

}

激活紋理

void Bind_Texture(TEXTURE_PTR texture){

glEnable(GL_TEXTURE_2D);

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

}

 

評論