关于在学习 opengl 时遇到的 bug:在 glBegin 和 glEnd 中间使用 glLineWidth 的问题

碎碎念

在帮小田 @西瓜啵啵奶昔 改程序的时候遇到的 bug,虽然知道怎么修复,但在网上查不到产生此 bug 的原因,所以记一下,给大家避个雷。感谢好兄弟又帮我长见识(bushi

如果有小伙伴知道为什么会产生这种 bug,请教教我!


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 函数,其中的 display1display2 是两个样例,后文会提及:

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();
}

关于在学习 opengl 时遇到的 bug:在 glBegin 和 glEnd 中间使用 glLineWidth 的问题_第1张图片

然后是出现 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();
}

关于在学习 opengl 时遇到的 bug:在 glBegin 和 glEnd 中间使用 glLineWidth 的问题_第2张图片
可以发现,当我在 glBegin()glEnd() 中间设置 glLineWidth() 的时候,这个宽度并不会被应用。这还是可以理解的,但是更奇怪的是,我们的 drawString() 函数也没有生效,如果说状态机模型可以解释第一个问题的话,第二个问题我一直不知道该如何解释,网上也没有相关回答。

当然,这个 bug 还不只如此,如果我们先执行 display2 再执行 display1,那么显而易见,这个 bug 会照常存在,两个 display 函数里的文本都无法显示,线条宽度也没有改变:
关于在学习 opengl 时遇到的 bug:在 glBegin 和 glEnd 中间使用 glLineWidth 的问题_第3张图片
但是神奇的是,如果我们先执行 display1 再执行 display2,那么会是如下状况:
关于在学习 opengl 时遇到的 bug:在 glBegin 和 glEnd 中间使用 glLineWidth 的问题_第4张图片
它被正确执行了!但是这正是它危险,且容易被忽略的地方,因为它只是表面上是正确的,但这个 bug 本质上还是存在的,这可能会引起一些意想不到的问题,而且难以排查。

所以大家一定要避免在 glBegin()glEnd() 中间使用 glLineWidth()

你可能感兴趣的:(计算机图形学,opengl)