加載位圖文件
加載位圖,也就是把位圖讀取到內存空間,實現紋理的創建,加載位圖的函數說明一下:
AUX_RGBImageRec *LoadBMP(char *Filename) // 根據位圖文件的名稱進行加載
{
FILE *File=NULL; // 文件指針
if (!Filename) // 如果沒有指定位圖文件名稱就返回NULL
{
return NULL;
}
File=fopen(Filename,"r"); // 根據指定的位圖文件名稱,打開該位圖文件
if (File) // 如果位圖文件存在
{
fclose(File); // 因爲只是需要判斷問題是否存在,而不需要對位圖文件進行寫操作,所以關閉位圖文件
return auxDIBImageLoad(Filename); // 其實,只需要一個真正存在的位圖文件的名稱,實現加載位圖文件,並返回一個指針
}
return NULL; // 位圖文件加載失敗就返回NULL
}
上面實現加載位圖的函數中,AUX_RGBImageRec是glaux.h中定義的類型,該類型的定義如下所示:
/*
** RGB Image Structure
*/
typedef struct _AUX_RGBImageRec {
GLint sizeX, sizeY;
unsigned char *data;
} AUX_RGBImageRec;
首先,AUX_RGBImageRec類型是一個RGB圖像結構類型。該結構定義了三個成員:
sizeX —— 圖像的寬度;
sizeY —— 圖像的高度;
data; —— 圖形所包含的數據,其實也就是該圖形在內存中的像素數據的一個指針。
AUX_RGBImageRec類型的變量描述了一幅圖像的特徵。
上述函數中,調用了glaux.h庫文件中的auxDIBImageLoad函數,其實它是一個宏,函數原型爲auxRGBImageLoadW(LPCWSTR)或者auxRGBImageLoadA(LPCSTR),可以在該庫文件中找到它的定義,如下所示:
/* AUX_RGBImageRec * APIENTRY auxRGBImageLoad(LPCTSTR); */
#ifdef UNICODE
#define auxRGBImageLoad auxRGBImageLoadW
#else
#define auxRGBImageLoad auxRGBImageLoadA
#endif
AUX_RGBImageRec * APIENTRY auxRGBImageLoadA(LPCSTR);
AUX_RGBImageRec * APIENTRY auxRGBImageLoadW(LPCWSTR);
#ifdef UNICODE
#define auxDIBImageLoad auxDIBImageLoadW
#else
#define auxDIBImageLoad auxDIBImageLoadA
#endif
AUX_RGBImageRec * APIENTRY auxDIBImageLoadA(LPCSTR);
AUX_RGBImageRec * APIENTRY auxDIBImageLoadW(LPCWSTR);
宏auxDIBImageLoad實現的功能就是:根據指定的位圖名稱,將該位圖的信息加載到內存中,以便用來創建成爲紋理。
創建紋理並加載紋理
用於創建並加載紋理的函數爲LoadGLTextures,實現如下所示:
int LoadGLTextures() // 根據加載的位圖創建紋理
{
int Status=FALSE; // 指示紋理創建是否成功的標誌
AUX_RGBImageRec *TextureImage[6]; // 創建一個紋理圖像數組,這裏指定數組大小爲6
memset(TextureImage,0,sizeof(void *)*6); // 初始化紋理圖像數組,爲其分配內存
char *pictures[] = { // 創建一個位圖名稱數組,對應6幅位圖
"Data/No1.bmp",
"Data/No2.bmp",
"Data/No3.bmp",
"Data/No4.bmp",
"Data/No5.bmp",
"Data/No6.bmp"
};
for(int i=0; i<6; i++) // 遍歷位圖名稱數組,根據位圖名稱分別生成
{
if (TextureImage[i]=LoadBMP(pictures[i])) // 加載位圖i成功,修改狀態標誌變量Status爲TRUE
{
Status=TRUE;
glGenTextures(1, &texture[i]); // 爲第i個位圖創建紋理
glBindTexture(GL_TEXTURE_2D, texture[i]); // 將生成的紋理的名稱綁定到指定的紋理上
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[i]->sizeX, TextureImage[i]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[i]->data);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
if (TextureImage[i]) // 釋放位圖數組佔用的內存空間
{
if (TextureImage[i]->data)
{
free(TextureImage[i]->data);
}
free(TextureImage[i]);
}
}
return Status; // 創建紋理並加載,返回成功或者失敗的標誌Status
}
上述函數是創建和加載紋理的核心實現。
1、glGenTextures函數
其中,調用了glGenTextures函數,查看MSDN可以看到,聲明如下所示:
void glGenTextures(
GLsizei n,
GLuint * textures
);
函數參數的含義:
n —— 生成的紋理的名稱的個數;
textures —— 生成的紋理名稱所存儲位置的指針,也就是一個紋理數組的內存地址,或者說是數組首元素的內存地址。
函數被調用,會生成一系列紋理的名字,並存儲到指定的數組中。
2、glBindTexture函數
glBindTexture函數實現了將調用glGenTextures函數生成的紋理的名字綁定到對應的目標紋理上。該函數的聲明如下所示:
void glBindTexture(
GLenum target,
GLuint texture
);
函數參數的含義:
target —— 紋理被綁定的目標,它只能取值GL_TEXTURE_1D或者GL_TEXTURE_2D;
texture —— 紋理的名稱,並且,該紋理的名稱在當前的應用中不能被再次使用。
3、glTexImage2D函數
調用glTexImage2D函數,用來指定二維紋理圖像。該函數的聲明如下所示:
void glTexImage2D(
GLenum target,
GLint level,
GLint components,
GLsizei width,
GLsizei height,
GLint border,
GLenum format,
GLenum type,
const GLvoid *pixels
);
函數參數的含義:
target —— 指定目標紋理,必須爲GL_TEXTURE_2D;
level —— 指定圖像級別的編號,0表示基本圖像,其它可以參考MSDN;
components —— 紋理中顏色組件的編號,可是是1或2或3或4;
width —— 紋理圖像的寬度;
height —— 紋理圖像的高度;
border —— 紋理圖像的邊框寬度,必須是0或1;
format —— 指定像素數據的格式,一共有9個取值:GL_COLOR_INDEX、GL_RED、GL_GREEN、GL_BLUE、GL_ALPHA、GL_RGB、GL_RGBA、GL_BGR_EXT、GL_BGRA_EXT、GL_LUMINANCE、GL_LUMINANCE_ALPHA ,具體含義可以參考MSDN;
type —— 像素數據的數據類型,取值可以爲GL_UNSIGNED_BYTE, GL_BYTE, GL_BITMAP, GL_UNSIGNED_SHORT, GL_SHORT, GL_UNSIGNED_INT, GL_INT, and GL_FLOAT;
pixels —— 內存中像素數據的指針。
4、glTexParameteri函數
glTexParameteri函數或者glTexParameterf函數用來設置紋理參數,聲明如下所示:
void glTexParameterf(
GLenum target,
GLenum pname,
GLfloat param
);
void glTexParameteri(
GLenum target,
GLenum pname,
GLint param
);
函數參數的含義:
target —— 目標紋理,必須爲GL_TEXTURE_1D或GL_TEXTURE_2D;
pname —— 用來設置紋理映射過程中像素映射的問題等,取值可以爲:GL_TEXTURE_MIN_FILTER、GL_TEXTURE_MAG_FILTER、GL_TEXTURE_WRAP_S、GL_TEXTURE_WRAP_T,詳細含義可以查看MSDN;
param —— 實際上就是pname的值,可以參考MSDN。
另外,該類函數還有兩個:
void glTexParameterfv(
GLenum target,
GLenum pname,
const GLfloat *params
);
void glTexParameteriv(
GLenum target,
GLenum pname,
const GLint *params
);
上述程序中調用如下:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
功能就是實現線形濾波的功能,當紋理映射到圖形表面以後,如果因爲其它條件的設置導致紋理不能更好地顯示的時候,進行過濾,按照指定的方式進行顯示,可能會過濾掉顯示不正常的紋理像素。