在NeHe上,通过BMP文件来加载纹理,使用的是glaux.h函数库中的auxDIBImageLoad(Filename)函数来解决的,使用起来比较方便,可是,glaux.h这个函数库作为OpenGL平台发展的一个中间过渡产品,存在这不够稳定及功能不够完整的缺点,所以一般不使用这个函数库,而选择glut.h,以下是分别应用这两种函数库来实现纹理图像加载的实例:
1. 使用glaux.h函数库实现
主要由两个函数实现,分别是LoadBMP()与LoadGLTextures()。
Code
1 AUX_RGBImageRec *LoadBMP(char *Filename) // Loads A Bitmap Image
2 {
3 FILE *File = NULL;
4 if (!Filename) // Make Sure A Filename Was Given
5 {
6 return NULL; // If Not Return NULL
7 }
8 File = fopen(Filename,"r");
9 if(File)
10 {
11 fclose(File); // Close The Handle
12 return auxDIBImageLoad(Filename); // Load The Bitmap And Return A Pointer
13 }
14 return NULL;
15 }
Code
1int LoadGLTextures()
2{
3 int Status=FALSE; // Status Indicator
4 AUX_RGBImageRec *TextureImage[1]; // Create Storage Space For The Texture
5 memset(TextureImage,0,sizeof(void *)*1); //Set The Pointer To NULL
6 if (TextureImage[0]=LoadBMP("Data/NeHe.bmp"))
7 {
8 Status=TRUE; // Set The Status To TRUE
9 glGenTextures(1, &texture[0]); // Create The Texture Object
10 glBindTexture(GL_TEXTURE_2D, texture[0]);
11 glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
12 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
13 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
14 if (TextureImage[0]) // If Texture Exists
15 {
16 if (TextureImage[0]->data) // If Texture Image Exists
17 {
18 free(TextureImage[0]->data); // Free The Texture Image Memory
19 }
20
21 free(TextureImage[0]); // Free The Image Structure
22 }
23 return Status;
24 }
25
26
2.在glut.h函数库下实现
通过函数实现LoadTexture(LPTSTR szFileName, GLuint &texid)实现
Code
1#include<glut.h>
2bool LoadTexture(LPTSTR szFileName, GLuint &texid) // Creates Texture From A Bitmap File
3{
4 HBITMAP hBMP; // Handle Of The Bitmap
5 BITMAP BMP; // Bitmap Structure
6
7 glGenTextures(1, &texid); // Create The Texture
8 hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL), szFileName, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE );
9
10 if (!hBMP) // Does The Bitmap Exist?
11 return FALSE; // If Not Return False
12
13 GetObject(hBMP, sizeof(BMP), &BMP); // Get The Object
14 // hBMP: Handle To Graphics Object
15 // sizeof(BMP): Size Of Buffer For Object Information
16 // &BMP: Buffer For Object Information
17
18 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // Pixel Storage Mode (Word Alignment / 4 Bytes)
19
20 // Typical Texture Generation Using Data From The Bitmap
21 glBindTexture(GL_TEXTURE_2D, texid); // Bind To The Texture ID
22 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Linear Min Filter
23 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Mag Filter
24 glTexImage2D(GL_TEXTURE_2D, 0, 3, BMP.bmWidth, BMP.bmHeight, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);
25
26 DeleteObject(hBMP); // Delete The Object
27
28 return TRUE; // Loading Was Successful
29}
30
其中有三个函数需要进一步的解释,分别是LoadImage(),GetModuleHandle,GetObject()。
LoadImage()在系统中的定义如下:
Code
1WINUSERAPI
2HANDLE
3WINAPI
4LoadImageA(
5 HINSTANCE,
6 LPCSTR,
7 UINT,
8 int,
9 int,
10 UINT);
11
12WINUSERAPI
13HANDLE
14WINAPI
15LoadImageW(
16 HINSTANCE,
17 LPCWSTR,
18 UINT,
19 int,
20 int,
21 UINT);
22
23#ifdef UNICODE
24#define LoadImage LoadImageW
25#else
26#define LoadImage LoadImageA
27#endif // !UNICODE
28
29
参数分别表示如下:
HINSTANCE---------包含所需要图片的实例的句柄。
LPCSTR--------------图片所在路径及文件名。
UINT-------------------图片类型。
int-----------------------图片宽度。
int-----------------------图片高度。
UINT-------------------load flags(具体意义还没有弄清楚)
而在LoadImage函数中HINSTANCE参数是通过GetModuleHandle(NULL)获取的,GetModuleHandle的函数声明如下:
HMODULE GetModuleHandle( LPCTSTR lpModuleName);
函数的声明挺简单的,但对这个函数的解释却不少,解释如下:
用指针指向一个包含模块名以NULL字符结尾的串,模块是.dll或.exe文件。如果文件扩展名省略,则增加默认的扩展名.dll。文件名串可以是省略号(...),表示模块名没有扩展名。这个串不是必须指定一个路径。当指定一个路径时,确定要用反斜线(\),而不是斜线(/)。这个模块名将和当前映射到调用进程地址空间的模块名进行独立地比较。假如这个参数是NULL,函数将返回创建调用进程(.exe文件)的文件的句柄。
如果函数调用成功,返回值是某一模块的句柄。如果函数调用失败,返回NULL。
最后就是GetObject()函数的注释,如下:
函数原型:int GetObject(HGDIOBJ hgdiobj, int cbBuffer, LPVOID lpvObject);
参数:
hgdiobj:指向感兴趣的图形对象的句柄,它可以是这样的一个句柄:一个逻辑位图、一个刷子、一种字体、一个调色板、笔或通过调用CreateDIBsection函数创建的与设备无关位图。
cbBuffer:指定将要写到缓冲区的信息的字节数目。
lpvObject:指向一个缓冲区的指针,该缓冲区将要检索指定图形对象的信息。
这三个参数暂时还不能完全的理解,只是现在会使用就够了,以后再做深究。
好了,以上两种情况下的BMP纹理图像的加载就是这么多,如果以后有更好的方法再做更新。
特别需要注意的一点是,以上两种方法加载对.bmp位图的纹理图片,在加载之前应仔细检查图片是不是.bmp格式的,检查方法,用二进制工具UltraEdit打开图片,若开头两个字符数是"BM",说明是.bmp文件,否则不是.