使用OpengL ES 显示文字的实现 (Wince)
使用OpengL ES 显示文字对opengl es 初学者来说,可谓一个不大不小的麻烦。有人是利用了Opengl ES API封装了一些dll库来实现,例如glfont,不过用起来就像浮云,很不灵活。这里简单描述下,我在wince上实现opengl es显示文字的思路。显示文字的实质其实也就是显示一张纹理,显示一个纹理很简单,那么我们的重点即是如何产生一个上面写有文字的纹理。
实现的思路是这样的:
1.创建一张与设备相关的GDI位图。
2.创建一个兼容DC,把步骤1创建的位图选入到DC中。
3.调用GDI,DrawText等把文字画到步骤2创建的DC上(可以用Truetype实现更加平滑的漂亮文字)。
4.利用此已画好文字的DC,再创建一个设备无关的位图,并用其像素数据生成纹理。
补充:对于需要把文字写在一个底图上的情况,我想也不用多述了吧,需要进行透明的文字显示时,亦可在此思路上略做补充就得了。
下面给出参考代码,注意代码的组织顺序跟我上面说的思路有点出入。
bool CDrawText::CreateText(CString strText,GLuint *id) //创建文字纹理无底图
{
CRect TextOffsetRect;
if(m_bDown)
TextOffsetRect = m_ActiveOffsetRect;
else
TextOffsetRect = m_OffsetRect;
int TextWidth = m_EffectRect.Width(); //图片宽度
int TextHeight = m_EffectRect.Height(); //图片高度
CFont m_font;
m_font.CreateFont(m_FontSize, /*< 字体高度 */
0, /*< 字体宽度 */
0, /*< 字体的旋转角度 Angle Of Escapement */
0, /*< 字体底线的旋转角度Orientation Angle */
m_iWeight, /*< 字体的重量 */
m_bItalic, /**< 是否使用斜体 */
m_bUnderLine, /**< 是否使用下划线 */
FALSE, /*< 是否使用删除线 */
ANSI_CHARSET, /*< 设置字符集 */
OUT_DEFAULT_PRECIS, /**< 输出精度 */
CLIP_DEFAULT_PRECIS, /*< 裁剪精度 */
/*ANTIALIASED_QUALITY*/CLEARTYPE_COMPAT_QUALITY, /**< 输出质量 */
FF_DONTCARE|DEFAULT_PITCH, /*< Family And Pitch */
L"宋体");
CDC* pDC = new CDC;
pDC->Attach(GetHDC());
//定义指向DIB数据区的指针
BYTE *lpBitmapBits = NULL;
CDC dcMem; //绘制最终结果的DC
dcMem.CreateCompatibleDC(pDC);
HDC hMemDC = dcMem.GetSafeHdc();
BITMAPINFO bitInfo;
bitInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bitInfo.bmiHeader.biWidth=TextWidth;
bitInfo.bmiHeader.biHeight=-TextHeight;
bitInfo.bmiHeader.biPlanes=1;
bitInfo.bmiHeader.biBitCount=24;
bitInfo.bmiHeader.biCompression=BI_RGB;
bitInfo.bmiHeader.biSizeImage=0;
bitInfo.bmiHeader.biXPelsPerMeter=0;
bitInfo.bmiHeader.biYPelsPerMeter=0;
bitInfo.bmiHeader.biClrUsed=0;
bitInfo.bmiHeader.biClrImportant=0;
bitInfo.bmiColors[0].rgbBlue=255;
bitInfo.bmiColors[0].rgbGreen=255;
bitInfo.bmiColors[0].rgbRed=255;
bitInfo.bmiColors[0].rgbReserved=255;
//创建位图
HBITMAP directBmp = CreateDIBSection(hMemDC, (BITMAPINFO*)&bitInfo,
DIB_RGB_COLORS, (void **)&lpBitmapBits, NULL, 0);
HGDIOBJ previousObject = SelectObject(hMemDC, directBmp);
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC,TextWidth,TextHeight);
CDC dcBmp; //后台绘制图片的DC,最终要将此DC Blt到dcMem中
dcBmp.CreateCompatibleDC(pDC);
CBitmap* COldBitamp = (CBitmap*)dcBmp.SelectObject(&bmp);
HDC hBmpDC = dcBmp.GetSafeHdc();
/* img.Draw2(dcBmp.GetSafeHdc(),0,0,iImgWidth,iImgHeight); //绘制图片到BmpDC中*/
dcBmp.FillSolidRect(CRect(0,0,TextWidth,TextHeight),m_BackColor);
int len=strText.GetLength();
CFont* COldFont = (CFont*)dcBmp.SelectObject(&m_font);
dcBmp.SetBkMode(TRANSPARENT);
if(!m_bDown)
dcBmp.SetTextColor(m_FontColor);
else
dcBmp.SetTextColor(m_ActiveFontColor);
dcBmp.DrawText(strText,len,&TextOffsetRect,m_uAlign);
BitBlt(hMemDC,0,0,TextWidth,TextHeight,hBmpDC,0,0,SRCCOPY);
int tmpPower = 2;
bool bGetW = false,bGetH = false;
while (true)
{
if (TextWidth <= tmpPower && !bGetW)
{
m_wBkImgx = tmpPower;
bGetW = true;
}
if (TextHeight <= tmpPower && !bGetH)
{
m_wBkImgy = tmpPower;
bGetH = true;
}
if (bGetW&&bGetH)
break;
tmpPower += tmpPower;
}
//GLubyte* pTexture = (GLubyte *)malloc(sizeof(GLubyte) * m_wBkImgx * m_wBkImgy *4);
if (pTexture == NULL)
{
TRACE(L"malloc mem fail");
TRACE(L"malloc mem fail");
return false;
}
memset(pTexture,0x00,m_wBkImgx * m_wBkImgy *4);
int nPitch = TextWidth*bitInfo.bmiHeader.biBitCount/8; //Width*3
while (nPitch%4) nPitch++;
LPBYTE lpData, lpLine, lpCurPixel;
lpData = lpLine = lpBitmapBits;
int nBytesPP = bitInfo.bmiHeader.biBitCount >> 3;//左移三位即除以8,获取图像每像素字节数
int linepos = 0;
for (int i=m_wBkImgy-1;i>=m_wBkImgy-TextHeight;i--)//
{
lpLine = lpData + (linepos++) * nPitch;
for(int j = 0; j < TextWidth; j++)
{
lpCurPixel = lpLine + j * nBytesPP;
int pos = (i * m_wBkImgx + j)*4;
pTexture[pos++] = *(lpCurPixel + 2); //R
pTexture[pos++] = *(lpCurPixel + 1); //G
pTexture[pos++] = *lpCurPixel; //B
pTexture[pos++] = 255;//img.AlphaGet(j,linepos); //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_CLAMP_TO_EDGE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, nTexWidth, nTexHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, pTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_wBkImgx, m_wBkImgy, 0, GL_RGBA, GL_UNSIGNED_BYTE, pTexture);
m_TextTexture.size = m_wBkImgx * m_wBkImgy;
//free(pTexture);
dcBmp.SelectObject(COldFont);
dcBmp.SelectObject(COldBitamp);
m_font.DeleteObject();
bmp.DeleteObject();
dcBmp.DeleteDC();
SelectObject(hMemDC,previousObject);
DeleteObject(directBmp);
dcMem.DeleteDC();
pDC->Detach();
pDC->DeleteDC();
delete pDC;
return true;
}