在帮小田 @西瓜啵啵奶昔 改程序的时候遇到的 bug,虽然知道怎么修复,但在网上查不到产生此 bug 的原因,所以记一下,给大家避个雷。感谢好兄弟又帮我长见识(bushi
如果有小伙伴知道为什么会产生这种 bug,请教教我!
一些基础性的代码就不多展示,先放一些用到的函数,比如渲染文字:
void drawString(const char* str) {
static int isFirstCall = 1;
static GLuint lists;
if (isFirstCall) {
isFirstCall = 0;
lists = glGenLists(128);
wglUseFontBitmaps(wglGetCurrentDC(), 0, 128, lists);
}
for (; *str != '\0'; ++str) {
glCallList(lists + *str);
}
}
void selectFont(int size, int charset, const char* face) {
HFONT hFont = CreateFontA(size, 0, 0, 0, FW_MEDIUM, 0, 0, 0, charset, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, face);
HFONT hOldFont = (HFONT)SelectObject(wglGetCurrentDC(), hFont);
DeleteObject(hOldFont);
}
还有用于渲染的 display
函数,其中的 display1
和 display2
是两个样例,后文会提及:
void display() {
glLoadIdentity();
gluOrtho2D(0, 500, 0, 500);
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
display1();
//display2();
glutSwapBuffers();
}
现在开始复现这个 bug,先来看一个正常情况下的代码:
void display1() {
glColor3f(0, 1, 0);
glLineWidth(5);
glBegin(GL_LINES);
glVertex2f(150, 50);
glVertex2f(450, 350);
glEnd();
glPushMatrix();
glRasterPos2f(100, 300);
selectFont(48, DEFAULT_CHARSET, "");
drawString("Hello World");
glPopMatrix();
}
然后是出现 bug 的代码:
void display2() {
glColor3f(1, 0, 0);
glLineWidth(50);
glBegin(GL_LINES);
glLineWidth(20);
glVertex2f(100, 50);
glVertex2f(450, 400);
glEnd();
glPushMatrix();
glRasterPos2f(100, 400);
selectFont(20, DEFAULT_CHARSET, "");
drawString("Hello World");
glPopMatrix();
}
可以发现,当我在 glBegin()
和 glEnd()
中间设置 glLineWidth()
的时候,这个宽度并不会被应用。这还是可以理解的,但是更奇怪的是,我们的 drawString()
函数也没有生效,如果说状态机模型可以解释第一个问题的话,第二个问题我一直不知道该如何解释,网上也没有相关回答。
当然,这个 bug 还不只如此,如果我们先执行 display2
再执行 display1
,那么显而易见,这个 bug 会照常存在,两个 display
函数里的文本都无法显示,线条宽度也没有改变:
但是神奇的是,如果我们先执行 display1
再执行 display2
,那么会是如下状况:
它被正确执行了!但是这正是它危险,且容易被忽略的地方,因为它只是表面上是正确的,但这个 bug 本质上还是存在的,这可能会引起一些意想不到的问题,而且难以排查。
所以大家一定要避免在 glBegin()
和 glEnd()
中间使用 glLineWidth()
!