opengl显示文字
在目前的项目中因为有涉及到OpenGL文字输出之类的操作,于是做了一个总结,并把一个库进行了改进,在这里贴出来,希望大家能够在将来的编程中省去一些写细节代码的时间,同时也是抛砖引玉。首先,要注明的是唐明理先生的开源库还有OpenGL资料是相当宝贵的,也是我见过的许多资料中最好的,如果初学者有了一定的应用水平,看他的这些东西,提高会是飞速的,而且会顺利过渡到框架开发的思维。我们做游戏与图像编程,
在目前的项目中因为有涉及到OpenGL文字输出之类的操作,于是做了一个总结,并把一个库进行了改进,在这里贴出来,希望大家能够在将来的编程中省去一些写细节代码的时间,同时也是抛砖引玉。
首先,要注明的是唐明理先生的开源库还有OpenGL资料是相当宝贵的,也是我见过的许多资料中最好的,如果初学者有了一定的应用水平,看他的这些东西,提高会是飞速的,而且会顺利过渡到框架开发的思维。我们做游戏与图像编程,必须要有把握全局代码的意识,必须要了解程序架构还有经典常用的数据结构与事件机制,而这一切的学习我觉得看别人代码是最快的,特别是象他这样循序渐进的代码。
OpenGL是一个3D图形界面,在它上面显示文字有别于在Windows图形环境下显示文字。在OpenGL上文字需要一些特殊的方法,因为在3D图形界面上,有平面文字、3D文字之分。特别是汉字的显示要麻烦一些,因为OpenGL的底层不支持汉字的双字节编码。 本文的解决方案可以实现三种不同方式的文字显示:
常规文字
这种文字显示是一种高效能的、以位图方式绘制字体的方法,它采用了一种平面图形的方法,所以显示的是平面文字。只可惜,这个平面文字显示方法不能支持汉字。
3D文字
OpenGL中文字也可以作为3D对象来显示。这种3D文字可以缩放、旋转、贴图,有其它3D对象的所有特性。我们在程序还加入了对双字节汉字的特殊处理,所以它也能显示立体汉字。
平面汉字
OpenGL平面汉字。基本原理是:在系统内部建立一个确定字体的设备场景(MDC),用GDI方式将文字在设备场景中形成单色位图,再用OpenGL的平面位图显示函数glBitmap(…)将文字显示出来。
以下是源码:
//GLFont.h----------------------------------------------------------------------
// GLFont.h: interface for the CGLFont class.
#if !defined(AFX_GLFONT_H__88F1F000_50F5_452A_B95E_60ED83712FA5__INCLUDED_)
#define AFX_GLFONT_H__88F1F000_50F5_452A_B95E_60ED83712FA5__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
class CGLFont
{
public:
void entext(float x,float y, LPCTSTR str,HFONT hFont,float r,float g,float b);
void c3dtext(LPCTSTR str,HFONT hFont,float z);
void Printfc3d(LPCTSTR strText,HFONT hFont,float z=0.05f);
void Printftext(int x, int y, LPCTSTR lpszText,HFONT hFont);
void settext(float x,float y,LPCTSTR str,HFONT Font,float r,float g,float b);
CGLFont();
virtual ~CGLFont();
protected:
HFONT hFont;
};
#endif
//GLFont.cpp----------------------------------------------------------------------
CGLFont::CGLFont()
{
}
CGLFont::~CGLFont()
{
}
void CGLFont::entext( float x,float y, LPCTSTR str, HFONT hFont,
float r, float g, float b)
{ HDC hdc = wglGetCurrentDC();
SelectObject(hdc, hFont);
unsigned int Base = glGenLists(96);
wglUseFontBitmaps(hdc, 32, 96,Base);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glPushAttrib(GL_LIST_BIT);
glColor3f(r,g,b);
glRasterPos2f(x/100, y/100);
glListBase(Base - 32);
glCallLists(_tcslen(str), GL_UNSIGNED_BYTE, str);
glPopAttrib();
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glDeleteLists(Base, 96);
}
void CGLFont::c3dtext(LPCTSTR str,HFONT hFont,float z)
{ glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
Printfc3d(TEXT("立体汉字"),hFont,z);
glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
}
void CGLFont::Printfc3d(LPCTSTR strText,HFONT hFont,float z)
{ HDC hdc = wglGetCurrentDC();
HFONT hOldFont=(HFONT)::SelectObject(hdc,hFont);
UCHAR * pChar=(UCHAR*)strText/*.GetBuffer(strText.GetLength())*/;
int nListNum;
DWORD dwChar;
GLYPHMETRICSFLOAT pgmf[1];
glPushMatrix();
for(int i = 0; i < _tcslen(strText)/*strText.GetLength()*/; i++)
{ if(IsDBCSLeadByte((BYTE)pChar[i]))
{ dwChar=(DWORD)((pChar[i]<<8)|pChar[i+1]);
i++;
}
else dwChar = pChar[i];
nListNum = glGenLists(1);
wglUseFontOutlines( hdc,
dwChar,
1,
nListNum,
0.0f,
z,
WGL_FONT_POLYGONS,
pgmf
);
glCallList(nListNum);
glDeleteLists(nListNum, 1);
}
glPopMatrix();
//strText.ReleaseBuffer();
::SelectObject(hdc,hOldFont);
}
void CGLFont:: settext (float x,float y,LPCTSTR str,HFONT Font,float r,float g,float b)
{ glPushMatrix();
glPushAttrib(GL_CURRENT_BIT);
glDisable(GL_TEXTURE_2D);
//glDisable(GL_LIGHTING);
glColor3f(r,g,b);
//--坐标变换--begin
double X = x;
double Y = y;
double Z;
GLdouble ModeMatrix[16];
GLdouble ProjectMatrix[16];
GLint ViewPort[4];
glGetDoublev(GL_PROJECTION_MATRIX, ProjectMatrix);
glGetDoublev(GL_MODELVIEW_MATRIX, ModeMatrix);
glGetIntegerv(GL_VIEWPORT, ViewPort);
gluUnProject((GLdouble)x,(GLdouble)y,(GLdouble)Z,ModeMatrix,ProjectMatrix,ViewPort, &X, &Y, &Z);
//--坐标变换--end
glTranslatef(X,Y,-0.4f);
Printftext (0,0, str,Font);
//glEnable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glPopAttrib();
glPopMatrix();
}
void CGLFont:: Printftext (int x, int y, LPCTSTR lpszText,HFONT hFont)
{ //CBitmap bitmap;
BITMAP bm;
SIZE size;
HDC MDC = ::CreateCompatibleDC(0);
SelectObject(MDC,hFont);
::GetTextExtentPoint32(MDC,lpszText,_tcslen(lpszText),&size);
//bitmap.CreateBitmap(size.cx, size.cy, 1, 1, NULL);
HBITMAP hbm = CreateBitmap(
size.cx, // bitmap width, in pixels
size.cy, // bitmap height, in pixels
1, // number of color planes
1, // number of bits to identify color
NULL // color data array
);
HBITMAP oldBmp=(HBITMAP)SelectObject(MDC,hbm/*bitmap*/);
SetBkColor (MDC, RGB(0, 0, 0));
SetTextColor(MDC, RGB(255, 255, 255));
TextOut(MDC, 0, 0, lpszText, _tcslen(lpszText));
//bitmap.GetBitmap(&bm);
::GetObject(hbm, sizeof(BITMAP), &bm);
//把图片大小变为2的幂次方
size.cx = (bm.bmWidth + 31) & (~31);
int bufsize =size.cy * size.cx;
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 = 1;
binf->bmiHeader.biCompression = BI_RGB;
binf->bmiHeader.biSizeImage = bufsize;
UCHAR* Bits = new UCHAR[bufsize];
::GetDIBits(MDC,hbm,0,bm.bmHeight,Bits,binf,DIB_RGB_COLORS);
glPixelStorei(GL_UNPACK_ALIGNMENT ,1);
glRasterPos2i(x,y);
glBitmap(size.cx,size.cy,0,0,0,0,Bits);
delete[] Bits;
SelectObject(MDC, oldBmp);
::DeleteDC(MDC);
DeleteObject(hbm);
}
改写的主要目的是去掉(注释掉)了MFC的相关成份,改为由SDK实现,因为游戏中很少有人用MFC,有时候会发生代码冲突。但是STL在游戏中的应用却比较多,也很好用,看来MFC真的是先天不足。
调用示例:
//文字输出类
CGLFont* Font;
HFONT hFont,hFont0;
Font=new CGLFont();
//第一个参数是字号大小,最后一个是字体名称,其它的不想多说了,可以自己去查
hFont =CreateFont(-16,0,0,0,400,0,0,0,GB2312_CHARSET,0,0,0,FF_MODERN,TEXT("宋体"));
hFont0 =CreateFont(-48,0,0,0,800,0,0,0,GB2312_CHARSET,0,0,0,FF_MODERN,TEXT("黑体"));
Font->settext(100,726,"小屈屈的Blog",hFont,1.0f,1.0f,0.0f);
Font->settext(180,726,"上海飞来飞去多媒体创意有限公司",hFont,1.0f,1.0f,0.0f);
另外,程序中已经做了坐标转换,不管视口有多大,都可以用分辨率来定位,分辨率取决于CreateWindow函数中的设置。
结束!
更多推荐
所有评论(0)