openGL 知识点
1. 关于点
在 OpenGL 中,点的大小默认值为 1 个像素,不过可以通过 glPointSize 函数来改变点的大小。该函数的原型如下:
void glPointSize(GLfloat size);
参数 size 必须大于 0.0f,其默认值为 1.0f,单位是“像素”。需要注意的是,对于具体的 OpenGL 实现,点的大小存在一定的限度。如果设置的 size 超过最大值,可能会导致设置出现问题。
以下是一个示例代码:
void myDisplay(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPointSize(5.0f);
glBegin(GL_POINTS);
glVertex2f(0.0f, 0.0f);
glVertex2f(0.5f, 0.5f);
glEnd();
glFlush();
}
2. 关于直线
2.1 指定直线宽度
可以使用 glLineWidth 函数来指定直线的宽度,其用法与 glPointSize 类似。函数原型如下:
void glLineWidth(GLfloat width);
2.2 绘制虚线
若要绘制虚线,首先需要使用 glEnable(GL_LINE_STIPPLE) 来启用虚线模式,使用 glDisable(GL_LINE_STIPPLE) 则可以关闭该模式。然后,使用 glLineStipple 函数来设置虚线的样式。其函数原型如下:
void glLineStipple(GLint factor, GLushort pattern);
参数 pattern 是一个由 1 和 0 组成的长度为 16 的序列,从最低位开始分析,如果为 1,则直线上接下来应该绘制的 factor 个点将被绘制为实的;如果为 0,则直线上接下来应该绘制的 factor 个点将被绘制为虚的。
示例图片来自 www.opengl.org,该图片是《OpenGL 编程指南》一书的附图。由于该书的旧版(第一版,1994 年)已经在网络上流传,希望没有触及到版权问题。
以下是示例代码:
void myDisplay(void) {
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_LINE_STIPPLE);
glLineStipple(2, 0x0F0F);
glLineWidth(10.0f);
glBegin(GL_LINES);
glVertex2f(0.0f, 0.0f);
glVertex2f(0.5f, 0.5f);
glEnd();
glFlush();
}
3. 关于多边形
多边形的相关内容较多,下面将从四个方面进行详细讲述。
3.1 多边形的两面以及绘制方式
尽管目前尚未真正使用三维坐标来绘图,但建立一些三维概念是很有必要的。从三维角度来看,一个多边形具有两个面,每个面都可以设置不同的绘制方式,包括填充、只绘制边缘轮廓线、只绘制顶点,其中“填充”是默认的绘制方式,并且可以为两个面分别设置不同的绘制方式。示例代码如下:
glPolygonMode(GL_FRONT, GL_FILL); // 设置正面为填充方式
glPolygonMode(GL_BACK, GL_LINE); // 设置反面为边缘绘制方式
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); // 设置两面均为顶点绘制方式
3.2 反转
一般约定“顶点以逆时针顺序出现在屏幕上的面”为“正面”,另一个面则为“反面”。在生活中,常见物体的表面通常可以通过这种“正面”和“反面”的方式“合理地”表现出来。例如,找一个比较透明的矿泉水瓶子,在正对你的一面沿逆时针画一个圆,并标明画的方向,然后将背面转为正面,再画一个类似的圆,就可以体会到“正面”和“反面”的概念。会发现正对你的方向,瓶的外侧是正面,而背对你的方向,瓶的内侧才是正面,正对你的内侧和背对你的外侧则是反面。这样,同样属于“瓶的外侧”这个表面,但某些地方算是正面,某些地方却算是反面。
不过,也有一些特殊的表面,例如“麦比乌斯带”(可自行 Google 了解),可以全部使用“正面”或全部使用“背面”来表示。可以通过 glFrontFace 函数来交换“正面”和“反面”的概念。示例代码如下:
glFrontFace(GL_CCW); // 设置 CCW 方向为“正面”,CCW 即 CounterClockWise,逆时针
glFrontFace(GL_CW); // 设置 CW 方向为“正面”,CW 即 ClockWise,顺时针
下面是一个示例程序,可以用它替换第一课中的 myDisplay 函数,并将 glFrontFace(GL_CCW) 修改为 glFrontFace(GL_CW),观察结果的变化。
void myDisplay(void) {
glClear(GL_COLOR_BUFFER_BIT);
glPolygonMode(GL_FRONT, GL_FILL); // 设置正面为填充模式
glPolygonMode(GL_BACK, GL_LINE); // 设置反面为线形模式
glFrontFace(GL_CCW); // 设置逆时针方向为正面
glBegin(GL_POLYGON); // 按逆时针绘制一个正方形,在左下方
glVertex2f(-0.5f, -0.5f);
glVertex2f(0.0f, -0.5f);
glVertex2f(0.0f, 0.0f);
glVertex2f(-0.5f, 0.0f);
glEnd();
glBegin(GL_POLYGON); // 按顺时针绘制一个正方形,在右上方
glVertex2f(0.0f, 0.0f);
glVertex2f(0.0f, 0.5f);
glVertex2f(0.5f, 0.5f);
glVertex2f(0.5f, 0.0f);
glEnd();
glFlush();
}