从网上看了几个关于这方面的帖子,可惜都没有把代码写全,写的比较全的那个用的我下面#if 0 … #else之间注释的方法,得到的文字效果很差,大片的纹理位置是空的,干扰了我对文字大小修改后文字的显示效果,最终将glBitmap方式绘制的屏幕贴图方式代码进行修改后使其支持三维方式纹理贴图模式。有兴趣就看看下面的代码吧,可以直接放到程序中使用的。
下面的代码是从glBitmap方式绘制文字的方法进行修改后得到的,速度比较快,结合显示列表,只生成一次,下次绘制直接调用显示列表将大大提高渲染速度。
bool CreateText(HFONT hFont ,LPCWSTR lpszText, unsigned int &tex)
{
HDC hdc = wglGetCurrentDC();
HFONT hOldFont = (HFONT)SelectObject(hdc,hFont);
int nTexWidth,nTexHeight;
HBITMAP _hBmp = NULL;
SIZE size;
#if 0 // 这种方法得到的位图尺寸变形很大????
::GetTextExtentPoint32(hdc, lpszText, len, &size);
HDC hMemDC = ::CreateCompatibleDC(hdc);
nTexWidth = size.cx;
nTexHeight = size.cy;
BITMAPINFO bmi;
ZeroMemory(&bmi.bmiHeader, sizeof(BITMAPINFOHEADER));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = nTexWidth;
bmi.bmiHeader.biHeight = nTexHeight;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
//(这里需要定义一个指针指向位图的数据:
BYTE * _pBmpBits; // 位图的数据指针)
_hBmp = CreateDIBSection( hMemDC, &bmi, DIB_RGB_COLORS,
(void **) &pBmpBits, NULL, 0 );
if ( NULL == _hBmp || NULL == pBmpBits)
{
return false;
}
// 将hBmp和hFont加入到hDc
SelectObject( hMemDC, _hBmp );
SetBkColor(hMemDC, RGB(0, 0, 0));
SetTextColor(hMemDC, RGB(255, 255, 255));
SetBkMode(hMemDC, OPAQUE);
TextOut(hMemDC, 0, 0, lpszText, len);
int nBitBytes = bmi.bmiHeader.biBitCount / 8;
for (int index = 0; index < nTexHeight*nTexWidth*nBitBytes; index+=nBitBytes)
{
pBmpBits[index+3] = (pBmpBits[index] > 0) ? 0xff : 0x00;
}
#else // 这种算法得到的图象是经过字符反走样后的结果,显示效果佳(推荐)
UCHAR *pBmpBits = NULL;
::GetTextExtentPoint32(hdc, lpszText, wcslen(lpszText), &size);
HBITMAP hbitmap = CreateBitmap(size.cx, size.cy,1,32, NULL);
if(!hbitmap)
return false;
HDC hMemDC = ::CreateCompatibleDC(hdc);
if(hMemDC)
{
HBITMAP hPrevBmp = (HBITMAP)SelectObject(hMemDC,hbitmap);
HFONT hPrevFont = (HFONT)SelectObject(hMemDC, hFont);
SetBkColor(hMemDC, RGB(0, 0, 0));
SetTextColor(hMemDC, RGB(255, 255, 255));
SetBkMode(hMemDC, OPAQUE);
TextOut(hMemDC, 0, 0, lpszText, wcslen(lpszText));
// copy GDI bitmap to DIB
BITMAP bm;
SelectObject(hdc,hbitmap);
GetObject(hbitmap, sizeof(bm), &bm);
size.cx = bm.bmWidth; //(bm.bmWidth + 31) & (~31);
size.cy = bm.bmHeight;
nTexWidth = size.cx;
nTexHeight = size.cy;
int bufsize = size.cy * size.cx * 4;
pBmpBits = new UCHAR[bufsize];
memset(pBmpBits, 0, sizeof(UCHAR)*bufsize);
struct {
BITMAPINFOHEADER bih;
RGBQUAD col[2];
}bic;
BITMAPINFO *binf = (BITMAPINFO *)&bic;
binf->bmiHeader.biSize = sizeof(binf->bmiHeader);
binf->bmiHeader.biWidth = bm.bmWidth;
binf->bmiHeader.biHeight = bm.bmHeight;
binf->bmiHeader.biPlanes = 1;
binf->bmiHeader.biBitCount = 32;
binf->bmiHeader.biCompression = BI_RGB;
binf->bmiHeader.biSizeImage = bufsize;
binf->bmiHeader.biXPelsPerMeter = 1;
binf->bmiHeader.biYPelsPerMeter = 1;
binf->bmiHeader.biClrUsed = 0;
binf->bmiHeader.biClrImportant = 0;
::GetDIBits(hdc, hbitmap, 0, bm.bmHeight, pBmpBits, binf,DIB_RGB_COLORS);
int nBitBytes = binf->bmiHeader.biBitCount / 8;
for (int index = 0; index < nTexHeight*nTexWidth*nBitBytes; index+=nBitBytes)
{
pBmpBits[index+3] = (pBmpBits[index] > 0) ? 0xff : 0x00;
}
}
#endif
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nTexWidth, nTexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,pBmpBits);//_pBits);
DeleteDC(hMemDC);
if (!_hBmp) DeleteObject(_hBmp);
if ( pBmpBits) delete pBmpBits;
return true;
}