OpenGL初学者,一些东西一知半解。附源代码问关于在OpenGL中显示字符的问题~~~

blldw 2006-09-08 05:05:39
代码如下,问题在顶楼:

/*
* draw a flying plane base on GLTest and GLCombineTest Project
*/

#include <gl/glut.h>
#include <windows.h>
#include <math.h>
#include <stdio.h>

#define PI 3.14159265853
#define PL 4.0f
#define PW 2.0f
#define PH 2.0f
#define FAN_R 4.0f
#define DrawLine(x1, y1, z1, x2, y2, z2) \
glBegin(GL_LINES); \
glVertex3f(x1, y1, z1); \
glVertex3f(x2, y2, z2); \
glEnd();

#define DrawBox() \
glBegin(GL_LINE_LOOP); \
glVertex3f(-1.0f, -1.0f, 1.0f); \
glVertex3f( 1.0f, -1.0f, 1.0f); \
glVertex3f( 1.0f, 1.0f, 1.0f); \
glVertex3f(-1.0f, 1.0f, 1.0f); \
glEnd(); \
glBegin(GL_LINE_LOOP); \
glVertex3f(-1.0f, -1.0f, -1.0f); \
glVertex3f(-1.0f, 1.0f, -1.0f); \
glVertex3f( 1.0f, 1.0f, -1.0f); \
glVertex3f( 1.0f, -1.0f, -1.0f); \
glEnd(); \
glBegin(GL_LINE_LOOP); \
glVertex3f(-1.0f, 1.0f, -1.0f); \
glVertex3f(-1.0f, 1.0f, 1.0f); \
glVertex3f( 1.0f, 1.0f, 1.0f); \
glVertex3f( 1.0f, 1.0f, -1.0f); \
glEnd(); \
glBegin(GL_LINE_LOOP); \
glVertex3f(-1.0f, -1.0f, -1.0f); \
glVertex3f( 1.0f, -1.0f, -1.0f); \
glVertex3f( 1.0f, -1.0f, 1.0f); \
glVertex3f(-1.0f, -1.0f, 1.0f); \
glEnd(); \
glBegin(GL_LINE_LOOP); \
glVertex3f( 1.0f, -1.0f, -1.0f); \
glVertex3f( 1.0f, 1.0f, -1.0f); \
glVertex3f( 1.0f, 1.0f, 1.0f); \
glVertex3f( 1.0f, -1.0f, 1.0f); \
glEnd(); \
glBegin(GL_LINE_LOOP); \
glVertex3f(-1.0f, -1.0f, -1.0f); \
glVertex3f(-1.0f, -1.0f, 1.0f); \
glVertex3f(-1.0f, 1.0f, 1.0f); \
glVertex3f(-1.0f, 1.0f, -1.0f); \
glEnd();

void init()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glShadeModel(GL_FLAT);

glEnable(GL_DEPTH_TEST);
}

void idle()
{
/*
static DWORD dwLastShow = timeGetTime();
DWORD dwCur;

// i want to 45 frame per second
dwCur = timeGetTime();
while (dwCur - dwLastShow < (1000 / 60))
dwCur = timeGetTime();
dwLastShow = dwCur;
*/
glutPostRedisplay();
}

void reshape(GLsizei width, GLsizei height)
{
glViewport(0, 0, width, height);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (GLdouble)width / (GLdouble)height, 1.0, 1000.0f);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

gluLookAt(0.0, 0.0, 80.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
//gluLookAt(0.0, 10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

void keyboard(unsigned char key, int x, int y)
{
static bool bAnimate = false;
switch (key)
{
case ' ':
bAnimate = !bAnimate;
if (bAnimate)
glutIdleFunc(idle);
else
glutIdleFunc(NULL);
break;

case 27:
exit(0);
break;
}
}

void showText(char *str)
{
if (lstrlen(str) == 0)
return;

SIZE size;
HDC hDC = CreateCompatibleDC(NULL);
GetTextExtentPoint32(hDC, str, lstrlen(str), &size);
HANDLE hFont =CreateFont(-12,0,0,0,400,0,0,0,GB2312_CHARSET,0,0,0,FF_MODERN,"宋体");
HBITMAP hBitmap = CreateCompatibleBitmap(hDC, size.cx, size.cy);
SelectObject(hDC, hFont);
SelectObject(hDC, hBitmap);
SetBkColor(hDC, RGB(0, 0, 0));
//SetBkMode(hDC, TRANSPARENT);
SetTextColor(hDC, RGB(255, 255, 255));
TextOut(hDC, 0, 0, str, lstrlen(str));

BITMAP bmp;
GetObject(hBitmap, sizeof(bmp), &bmp);

// compute buffer size
int width = ((size.cx + 31) & (~31)) / 8;
int height = size.cy;
int bufSize = width * height;

RGBQUAD rgbEntries[2] = { { 0, 0, 0, 0 }, { 255, 255, 255, 0 } };
BITMAPINFO *pbmpinfo = new BITMAPINFO;
ZeroMemory(pbmpinfo, sizeof(BITMAPINFO));
pbmpinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
pbmpinfo->bmiHeader.biWidth = bmp.bmWidth;
pbmpinfo->bmiHeader.biHeight = bmp.bmHeight;
pbmpinfo->bmiHeader.biPlanes = 1;
pbmpinfo->bmiHeader.biBitCount = 1;
pbmpinfo->bmiHeader.biCompression = BI_RGB;
pbmpinfo->bmiHeader.biClrUsed = 2;
pbmpinfo->bmiHeader.biClrImportant = 0;
pbmpinfo->bmiHeader.biXPelsPerMeter = 0;
pbmpinfo->bmiHeader.biYPelsPerMeter = 0;
pbmpinfo->bmiHeader.biSizeImage = bufSize;
//CopyMemory(pbmpinfo + sizeof(BITMAPINFOHEADER), &rgbEntries[0], sizeof(RGBQUAD)*2);

BYTE *pBuf = new BYTE[bufSize];
GetDIBits(hDC, hBitmap, 0, bmp.bmHeight, pBuf, pbmpinfo, DIB_RGB_COLORS);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

// 想在左下角显示字符串
int vp[4];
glGetIntegerv(GL_VIEWPORT, vp);
glRasterPos2i(0, 0);
glBitmap(bmp.bmWidth, bmp.bmHeight, 0, 0, 0, 0, pBuf);
delete pBuf;
DeleteDC(hDC);
}

void display()
{
static float angleFan = 0.0f;
static float angleBody = 0.0f;
static DWORD dwLastTime = timeGetTime();
static int frames = 0;
static char szfps[128] = { 0 };

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPushMatrix();
// draw the body first
glRotatef(angleBody, 0.0f, 1.0f, 0.0f);
glRotatef(-30.0f, 1.0f, 0.0f, 0.0f);
glTranslatef(-30.0f, 15.0f, 0.0f);
glColor3f(1.0f, 0.0f, 0.0f);

// here put glScalef between glPushMatrix and glPopMatrix will affect only plane body
glPushMatrix();
glScalef(PL, PH, PW);
DrawBox();
glPopMatrix();

// draw the pole connecting body and fans
glTranslatef(0.0f, PH, 0.0f);
DrawLine(0.0f, 0.0f, 0.0f, 0.0f, PH, 0.0f);

// draw fans(6)
glColor3f(0.0f, 1.0f, 0.0f);
glTranslatef(0.0f, PH, 0.0f);
glPushMatrix(); // fan1
glRotatef(0.0f + angleFan, 0.0f, 1.0f, 0.0f);
DrawLine(0.0f, 0.0f, 0.0f, FAN_R, 0.0f, 0.0f);
glPopMatrix();
glPushMatrix(); // fan2
glRotatef(60.0f + angleFan, 0.0f, 1.0f, 0.0f);
DrawLine(0.0f, 0.0f, 0.0f, FAN_R, 0.0f, 0.0f);
glPopMatrix();
glPushMatrix(); // fan3
glRotatef(120.0f + angleFan, 0.0f, 1.0f, 0.0f);
DrawLine(0.0f, 0.0f, 0.0f, FAN_R, 0.0f, 0.0f);
glPopMatrix();
glPushMatrix(); // fan4
glRotatef(180.0f + angleFan, 0.0f, 1.0f, 0.0f);
DrawLine(0.0f, 0.0f, 0.0f, FAN_R, 0.0f, 0.0f);
glPopMatrix();
glPushMatrix(); // fan5
glRotatef(240.0f + angleFan, 0.0f, 1.0f, 0.0f);
DrawLine(0.0f, 0.0f, 0.0f, FAN_R, 0.0f, 0.0f);
glPopMatrix();
glPushMatrix(); // fan6
glRotatef(300.0f + angleFan, 0.0f, 1.0f, 0.0f);
DrawLine(0.0f, 0.0f, 0.0f, FAN_R, 0.0f, 0.0f);
glPopMatrix();

// write text

glPopMatrix();

angleFan += 5.0f;
angleBody += 1.0f;

// fps
frames++;
if (frames == 5)
{
DWORD dwCur = timeGetTime();
float fps = 1000.0f * 5.0f / (float)(dwCur - dwLastTime);
dwLastTime = dwCur;
frames = 0;
sprintf(szfps, "current fps(祯率) = %.2f", fps);
glutSetWindowTitle(szfps);
}

showText(szfps);

glFlush();
glutSwapBuffers();
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
int argc = 1;
char *argv[] = { "GLPlane" };

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_DEPTH | GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(100, 100);
glutCreateWindow(argv[0]);
glutFullScreen();
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();

return 0;
}
...全文
435 点赞 收藏 5
写回复
5 条回复
blldw 2006年09月11日
Ok,结贴了,谢谢DRACULAX05的回答:)
回复 点赞
DRACULAX05 2006年09月10日
第一个问题如果你不相信的话,在showText前面加glColor3f(1.0f, 1.0f, 1.0f)再调showText,OpenGL使用状态机保存当前状态,glColor*就是修改状态的函数
第三个问题,我说的正投影你可以用glOrtho,设置投影方式只是改变投影矩阵,开销不大,如果不这样,是很难定位的
第四个问题,也许你是对的,但是我重来没有见过这样编的,hehe
回复 点赞
blldw 2006年09月10日
第一个问题:我本意是绘图输出黑底白字的文本,然后在用OpenGL函数显示在屏幕上,这样的话,glColor*应该就不会影响问题的颜色了吧
第三个问题:按照DRACULAX05说法,我要显示字符在左下角之前岂不是还要调用一个glMatrixMode(),这样的话在显示3D图形和2D文本的基础上就要反复设置投影方式了?
第四个问题:我是故意这么作的,是因为不想看到Console窗口,而且这么做运行的也很好。
回复 点赞
DRACULAX05 2006年09月10日
第一个问题:显示的字体颜色是由最近的一个glColorXX决定的,查找你的程序在showText(...)调用前最近的一个是glColor3f(0.0f, 1.0f, 0.0f);所以显示的字符为绿色。

第二个问题:你显示字符的方法绝对正确,OpenGL对文本的显示方法只此一家。这也是OpenGL被批地最多的地方——显示2D字符太麻烦

第三个问题:你设的glRasterPosi(0, 0)是正确的,但是要知道OpenGL默认坐标系是左下角为(0,0),y向上递增。你的程序问题在于显示之前没有转换投影方式,显示2D的东西一律要转换到正投影,否则会渲染前会用投影矩阵进行转换。根据这两点具体修改你自己做吧:)

第四个问题:你的程序框架是错的,你把控制台(console)格式的OpenGL框架套到Win32中了
回复 点赞
blldw 2006年09月08日
上述代码在VC++ 6.0环境下编译通过,现在有如下问题,请高手指教:
1,在OpengGl中显示字符的原理好像是把字符串显示在位图中,然后再调用glBitmap显示位图,应该还有其他的方法,但是我现在只知道这种方法。我将屏幕背景设成黑色,然后在上面显示白色字体,但是上述程序运行结果却始终显示是绿色的,不知道什么原因。
2,想在屏幕左下角显示字符串,该如何设置glRasterPosi()?

谢谢,暂时这两个问题
回复 点赞
发动态
发帖子
游戏开发
创建于2007-08-27

7200

社区成员

2.3w+

社区内容

游戏开发相关内容讨论专区
社区公告
暂无公告