Windows mobile系统下调用Opengl es,当我试图使用当前DC下的bitmap对象(DDB位图)作为材质贴图,执行3D表面贴图。但是这个操作还是比较曲折的:
我使用glTexImage2D函数绑定图像到3D表面,glTexImage2D函数要求携带的数据是图像像素阵列。我必须要从DDB位图取出数据,因此我通过DIB位图来操作,首先要建立一个使用DIB位图的内存DC,通过把DDB位图bitblt到这个内存DC中,从而取到DDB位图的像素阵列
//--------------DIB结构定义---------------------------
UINT iSize = sizeof(BITMAPINFO);
BITMAPINFO* pBMI = (BITMAPINFO*) malloc(iSize);
if( pBMI != NULL)
{
memset(pBMI, 0, iSize);
// Fill in the header info.
pBMI->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pBMI->bmiHeader.biWidth = 1024;
pBMI->bmiHeader.biHeight = 512;
pBMI->bmiHeader.biPlanes = 1;
pBMI->bmiHeader.biBitCount = 16; //
//pBMI->bmiHeader.biCompression = BI_BITFIELDS; // to use this flag.
pBMI->bmiHeader.biCompression = BI_RGB; // to use this flag.
}
else
{
return;
}
//--------------DIB结构定义---------------------------
//--------------创建DIB内存DC---------------------------
BYTE* pBits ;
HDC hdcTexture=CreateCompatibleDC(hdc);
//HBITMAP hbitmapTexture=CreateCompatibleBitmap(hdcTexture,1024,512);
HBITMAP hbitmapTexture = CreateDIBSection( hdcTexture,
pBMI,
DIB_RGB_COLORS,
//DIB_PAL_COLORS,
(VOID **) &pBits,
NULL,
0);
HBITMAP hbitmapTextureold=(HBITMAP)SelectObject(hdcTexture,hbitmapTexture);
//--------------创建DIB内存DC---------------------------
因此通过上述操作,我建立了一个hdcTexture,这个内存DC使用的是DIB位图,我要把从界面上得到的位图贴入这个内存DC
//取DC用于拼图
HDC hdc = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL);
//传进的两张位图数据
BITMAP bmp1;
BITMAP bmp2;
(void)GetObject(txtmap1,sizeof(BITMAP),&bmp1);//txtmap1是从外部传入的位图
(void)GetObject(txtmap2,sizeof(BITMAP),&bmp2);//txtmap2是从外部传入的位图
HDC hdcMemtxt1=CreateCompatibleDC(hdc);
HBITMAP holdmapMem1=(HBITMAP)SelectObject(hdcMemtxt1,txtmap1);
HDC hdcMemtxt2=CreateCompatibleDC(hdc);
HBITMAP holdmapMem2=(HBITMAP)SelectObject(hdcMemtxt2,txtmap2);
// txtStyle是外部传入的参数,表示拼图的样式
if(txtStyle)
{ StretchBlt(hdcTexture,0,0,512,512,hdcMemtxt2,0,0,bmp2.bmWidth,bmp2.bmHeight,SRCCOPY);
StretchBlt(hdcTexture,512,0,512,512,hdcMemtxt1,0,0,bmp1.bmWidth,bmp1.bmHeight,SRCCOPY);
}
else
{
StretchBlt(hdcTexture,0,0,512,512,hdcMemtxt1,0,0,bmp1.bmWidth,bmp1.bmHeight,SRCCOPY);
StretchBlt(hdcTexture,512,0,512,512,hdcMemtxt2,0,0,bmp2.bmWidth,bmp2.bmHeight,SRCCOPY);
}
SelectObject(hdcMemtxt1,holdmapMem1);
SelectObject(hdcMemtxt2,holdmapMem2);
SelectObject(hdcTexture,hbitmapTextureold);
此时我已经取得了我所需要的像素数据了,但是又遇到一个问题,当我直接把数据传入glTexImage2D函数时会发现整个图形的色彩都变了,我的函数是glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 1024, 512, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pbits);显然565格式与当前的像素阵列的格式不匹配,但是当我把参数改成GL_UNSIGNED_SHORT_5_5_5_1时也还是不对。因此我直接对原来的像素格式做了计算,同时执行了一次序列反转。
//--------------像素处理函数---------------------------
//像素格式转换
//pb1:源格式数据
//pixelW,pixelH:源图的像素尺寸
//实现格转换及数据翻转
BYTE* C3Dgles::ChangePixel555To565(BYTE* pb1,UINT pixelW,UINT pixelH) const
{
//位图像素集指针
DWORD dwSize = (DWORD)(pixelW * pixelH)*2;
//目的像素集指针
BYTE* pPixelPool = new BYTE[dwSize];
if(pPixelPool == NULL) return NULL;
memset(pPixelPool, 0, dwSize);
//移动源像素数据指针到最后一位
//BYTE* currSrcpx=pb1+dwSize;
BYTE* currSrcpx=NULL;
BYTE* pPixelPoolFirst=pPixelPool;
//像素循环
for(UINT i=0;i<pixelH;i++)
{
//从最后一行计算,移动数据指针到每行的开头
//currSrcpx=currSrcpx-(i+1)*pixelW*2;
currSrcpx=pb1+(pixelH-(i+1))*pixelW*2;
for(UINT j=0;j<pixelW;j++)
{
//currSrcpx=currSrcpx+1;
BYTE btTemp1=*currSrcpx++;
BYTE btDestTemp1=(BYTE)((btTemp1 & 0xE0)<<1)|(btTemp1 & 0x1F);
//currSrcpx--;
BYTE btTemp2=*currSrcpx++;
BYTE btDestTemp2=(BYTE)(btTemp2<<1)|((btTemp1 & 0x80)>>7);
*pPixelPool++=btDestTemp1;
*pPixelPool++=btDestTemp2;
}
}
return pPixelPoolFirst;
}
//--------------像素处理函数---------------------------
此时就能取得与配置相符合的数据,继续我的操作,完成这次内存贴图的功能
//拼合后的贴图数据
BITMAP bmpinfo;
(void)GetObject(hbitmapTexture,sizeof(BITMAP),&bmpinfo);
//BYTE* btbits=(BYTE*)bmpinfo.bmBits;
//数据转换
BYTE* pPixelWordPool = ChangePixel555To565((BYTE*)bmpinfo.bmBits,(UINT)bmpinfo.bmWidth,(UINT)bmpinfo.bmHeight);
//测试位图是否取得
//StretchBlt(hdc,0,0,480,640,hdcTexture,0,0,bmpinfo.bmWidth,bmpinfo.bmHeight,SRCCOPY);
DELETEP(pBits);
DELETEGDIOBJ(txtmap1);
DELETEGDIOBJ(txtmap2);
DELETEGDIOBJ(hbitmapTexture);
(void)DeleteDC(hdcMemtxt1);
(void)DeleteDC(hdcMemtxt2);
(void)DeleteDC(hdcTexture);
(void)DeleteDC(hdc);
free(pBMI);
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 1024, 512, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pbits);
DELETEP(pPixelWordPool);
return TRUE;