如有转载请注明出处:http://blog.csdn.net/tianhai110/
在3D游戏开发中,通常需要将文本变成纹理,以便于3D显示 。本文阐述了如何通过GDI来生成D3D纹理的方法。
由于汉字多达5000字以上,为每个汉字制作相应图片,显然是不现实的;并且不能够改变字体。 最容易想到的当然是WIN32的GDI绘字,这是最简单,最常用的方法,并且可以改变字体、大小、样式。但缺点也是显而易见的,如果每帧都不断切换GDI,性能将大打折扣。其实,D3D的 ID3DXFONT也是利用GDI来绘字,在direct3d 9.0以前的这个是相当慢的,dx9.0后,微软对其进行了大改,性能有了质的飞跃,但是实时绘制大量文字的时候性能仍然有很大的影响(我曾每帧绘制50行字,性能从300多帧,变为50多帧)。
思路:将文字用GDI绘制出来,然后保存成纹理(实际上,游戏中的文字通常要在屏幕上呆上一段时间),对这些纹理作下管理。通过构造一个顶点缓冲区来将纹理贴到一个四边形的块上去。
下面将GDI文字保存成IDirect3DTexture9的代码:
IDirect3DTexture9* texture
HDC hDc = ::CreateCompatibleDC( NULL); // 通过当前桌面创建设备内容HDC
SetTextColor( hDc, RGB( 255,255,255)); // 设置背景颜色和文字的颜色
SetBkColor( hDc, 0xff000000);
SetMapMode( hDc, MM_TEXT);
DWORD* pBitmapBits; // 创建一个位图
BITMAPINFO bitmapInfo;
ZeroMemory( &bitmapInfo.bmiHeader, sizeof(BITMAPINFOHEADER));
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo.bmiHeader.biWidth = 900;
bitmapInfo.bmiHeader.biHeight = 900;
bitmapInfo.bmiHeader.biPlanes = 1;
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biBitCount = 32;
HBITMAP hBitmap = CreateDIBSection( hDc, &bitmapInfo, DIB_RGB_COLORS, (VOID**)&pBitmapBits, NULL, 0);
SelectObject( hDc, hBitmap); // 将位图与HDC关联,这样文字时间上就保存在hBitmap里面了
LOGFONT lf;
ZeroMemory( &lf, sizeof(LOGFONT));
lf.lfHeight = 72;
lf.lfWidth = 0;
HFONT hFont = CreateFontIndirect(&lf); // 创建大小为72的字体
SelectObject(hDc, hFont);
TextOut( hDc,0,0,"在这里写字", strlen("在这里写字"));
BITMAP bmp;
GetObject( hBitmap, sizeof(BITMAP), &bmp);
BYTE* buffer;
int blength; // 整个hBitMap文件字节长度
blength = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmp.bmWidthBytes * bmp.bmHeight;
buffer = new BYTE[blength];
BITMAPINFOHEADER bi;
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = bmp.bmWidth;
bi.biHeight = bmp.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = bmp.bmBitsPixel;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrImportant = 0;
bi.biClrUsed = 0;
BITMAPFILEHEADER bmfHdr;
bmfHdr.bfType = 0x4D42; // "BM"
bmfHdr.bfSize = blength;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER);
memcpy( buffer, &bmfHdr, sizeof(BITMAPFILEHEADER));
memcpy( &buffer[sizeof(BITMAPFILEHEADER)], &bi, sizeof(BITMAPINFOHEADER));
memcpy( &buffer[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)],
bmp.bmBits, blength - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER));
// 将刚才构建好的bmp数据,转成IDirect3DTexture9* 的纹理
if ( FAILED( D3DXCreateTextureFromFileInMemory( g_pDev, buffer, blength, &texture)))
{
return S_FALSE;
}
delete[] buffer;
DeleteObject(hFont);
DeleteObject( hBitmap);
DeleteDC( hDc);