• 关于在学习 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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    还有用于渲染的 display 函数,其中的 display1display2 是两个样例,后文会提及:

    void display() {
    	glLoadIdentity();
    	gluOrtho2D(0, 500, 0, 500);
    	glClearColor(1, 1, 1, 1);
    	glClear(GL_COLOR_BUFFER_BIT);
    	display1();
    	//display2();
    	glutSwapBuffers();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    现在开始复现这个 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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    然后是出现 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();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

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

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

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

  • 相关阅读:
    APC12345
    Spring-Cloud-Openfeign如何传递用户信息?
    android studio开发flutter应用,使用mumu模拟器调试软件
    【算法竞赛入门练习题】判断输入的数字是否为回文数字的俩种方法,数字逆置的方法
    【k8s】4、资源管理命令-陈述式
    nginx配置详解
    2023最新SSM计算机毕业设计选题大全(附源码+LW)之java线上学习系统8e88w
    把所有的Linux命令制作成一张电脑壁纸,消耗了20红牛终于成了
    UNIAPP实战项目笔记34 购物车的单选和全选单选联动
    机器学习入门教学——决策树
  • 原文地址:https://blog.csdn.net/SP_FA/article/details/127717691