Wince下 Opengl ES 纹理的创建
This article describes how to create textures in Opengl ES application development. I list three methods and give an simple introduction only according to my experience .Only the key codes are given in this article and I shall not have any liability for its content.
1、用BMP图片文件中创建纹理,这是实现2维纹理最简单的方法,但是Bmp的存储要占大量的空间。这里要注意图片的格式是24-Bitmap.如果是16-Bitmap还要作转化。关键是要得到一张图片的每一个像素点的各个通道的值。
bool COpenGLES::LoadBMPTexture(char* filename,GLuint *texture)
{
BITMAPINFOHEADER* bmpInfo=new (BITMAPINFOHEADER);
FILE *file;
BITMAPFILEHEADER bmpFile;
unsigned char *bmpImage = NULL;
unsigned char tmpRGB ;
file = fopen(filename,"rb");
if (!file)
return false;
fread(&bmpFile,sizeof(BITMAPFILEHEADER),1,file);
if (bmpFile.bfType != 0x4D42)
{
fclose(file);
return false;
}
fread(bmpInfo,sizeof(BITMAPINFOHEADER),1,file);
fseek(file,bmpFile.bfOffBits,SEEK_SET);
bmpImage = new unsigned char[bmpInfo->biSizeImage];
if (!bmpImage)
{
MessageBox(NULL, L"Out of Memory", L"Error", MB_OK)
delete[] bmpImage;
fclose(file);
return false;
}
fread(bmpImage,1,bmpInfo->biSizeImage,file);
if (!bmpImage)
{
MessageBox(NULL, L"Error reading bitmap", L"Error", MB_OK);
fclose(file);
return false;
}
for (unsigned int i = 0; i < bmpInfo->biSizeImage; i+=3)
{
tmpRGB = bmpImage[i];
bmpImage[i] = bmpImage[i+2];
bmpImage[i+2] = tmpRGB;
}
fclose(file);
glGenTextures(1, texture);
glBindTexture(GL_TEXTURE_2D, *tex ture);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bmpInfo->biWidth, bmpInfo->biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bmpImage);
delete [] bmpImage;
delete bmpInfo;
return true;
}
2. 使用MS提供的处理图片对象的Com接口IImage,可以方便地进行对图片的解码和访问图片的属性和数据。只要在BSP包里添加了相应图片格式的解码组件,就可以使用这个Com接口来实现把诸如PNG/GIF/JPG等格式的图片创建成2维纹理。
bool COpenGLES::LoadBMPTexture(FILE* pFile,GLuint *id)
{
//获取图像大小信息
ImageInfo ImgInfo;
pImage->GetImageInfo(&ImgInfo);
int sizeX = ImgInfo.Width;
int sizeY = ImgInfo.Height;
if (FAILED(hr = pImgFactory->CreateBitmapFromImage(
pImage,sizeX,sizeY,PixelFormat24bppRGB,
InterpolationHintDefault,&pBmpImg)))
{
return false;
}
CRect rect(0,0,sizeX,sizeY);
BitmapData *BmpData = new BitmapData;
if (FAILED(hr = pBmpImg->LockBits(rect,
ImageLockModeRead|ImageLockModeRead,
PixelFormat24bppRGB,BmpData)))
{
return false;
}
int line = BmpData->Stride;
LPBYTE lpData, lpLine, lpCurPixel;
lpData = lpLine = (LPBYTE)BmpData->Scan0; //获取BMP位图实际值的地址指针
//若为Bottom-Up(从下到上)的位图,则指向buffer的结尾
//若为Top-Down(从上到下)的位图,则指向buffer的开头
// int nBytesPP = nBPP >> 3; //左移三位即除以8,获取图像每像素字节数
GLubyte* pTexture = new GLubyte[sizeX * sizeY * 3];
if (line>0)
{
int pos = sizeX * sizeY * 3-1;
for(int i = 0; i
{
lpLine = lpData + i * line; //获取图像每一行地址指针
for(int j = sizeX-1; j>-1; j--) //列
{
lpCurPixel = lpLine + j * 3; //获取每行每像素地址指针
pTexture[pos--] = *lpCurPixel ; //R
pTexture[pos--] = *(lpCurPixel + 1); //G
pTexture[pos--] = *(lpCurPixel + 2); //B
}
}
}
else
{
int pos = 0 ;
for(int i = sizeY-1; i>-1; i--) //行
{
lpLine = lpData + i * line; //获取图像每一行地址指针
for(int j = 0; j
{
lpCurPixel = lpLine + j * 3; //获取每行每像素地址指针
pTexture[pos++] = *(lpCurPixel + 2); //R
pTexture[pos++] = *(lpCurPixel + 1); //G
pTexture[pos++] = *lpCurPixel; //B
}
}
}
glGenTextures(1, id); //绑定纹理
glBindTexture(GL_TEXTURE_2D, *id);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, sizeX, sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, pTexture);
delete []pTexture;
if (FAILED(hr = pBmpImg->UnlockBits(BmpData)))
{
return false;
}
delete BmpData;
pBmpImg = NULL;
// pImage->Release();
// pImgFactory->Release();
return true;
}
3、使用第三方图片操作类库CXimage,CxImage类库可以快捷地存取、显示、转换各种图像,是免费的开源代码,很容易获得。利用这个类库也能轻易地创建纹理。
bool COpenGLES::LoadTexture(byte* pbuf,DWORD size,int format,GLuint *id)
{
DWORD imgformat = 0;
switch (format)
{
case 1:
imgformat = CXIMAGE_FORMAT_PNG;
break;
case 2:
imgformat = CXIMAGE_FORMAT_JPG;
break;
case 3:
imgformat = CXIMAGE_FORMAT_BMP;
default:
break;
}
CxImage img(pbuf,size,imgformat);
if(!img.IsValid())
return false;
int nBPP = img.GetBpp();
if(!((nBPP == 24)||(nBPP == 32))) //只支持24,32位
{
img.Clear();
img.Destroy();
img.SelectionClear();
return false;
}
int nWidth = img.GetWidth();
int nHeight = img.GetHeight();
int nTexWidth = nWidth;
int nTexHeight = nHeight;
if ( 0 != nWidth%2)
{
nTexWidth = nWidth + 1;
}
if (0 != nHeight%2)
{
nTexHeight = nHeight +1;
}
GLubyte* pTexture = new GLubyte[nTexWidth * nTexHeight * 3];
int nPitch = img.GetEffWidth();
LPBYTE lpData, lpLine, lpCurPixel;
lpData = lpLine = (LPBYTE)img.GetBits();
int nBytesPP = nBPP >> 3;//左移三位即除以8,获取图像每像素字节数
for(int i = 0; i < nHeight; i++)
{
lpLine = lpData + i * nPitch;
for(int j = 0; j < nWidth; j++)
{
lpCurPixel = lpLine + j * nBytesPP;
pTexture[(i * nTexWidth + j)*3] = *(lpCurPixel + 2); //R
pTexture[(i * nTexWidth + j)*3 + 1] = *(lpCurPixel + 1); //G
pTexture[(i * nTexWidth + j)*3 + 2] = *lpCurPixel; //B
//pTexture[(i * nTexWidth + j)*4 + 3] = 255; //A
}
for (int j = nWidth;j< nTexWidth;j++)
{
pTexture[(i * nTexWidth + j)*3] = 0; //R
pTexture[(i * nTexWidth + j)*3 + 1] = 0; //G
pTexture[(i * nTexWidth + j)*3 + 2] = 0; //B
//pTexture[(i * nTexWidth + j)*4 + 3] = 0; //A
}
}
glGenTextures(1, id); //绑定纹理
glBindTexture(GL_TEXTURE_2D, *id);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nTexWidth, nTexHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, pTexture);
delete []pTexture;
free(pTexture);
img.Clear();
img.Destroy();
img.SelectionClear();
// fseek(pFile,0L,0);
return true;
}