openGL 基础知识(一)绘制简单图形
1. 利用openGL画点、线、面
glBegin(所画类型)
这里设置画图所需要的点
glEnd()
openGL中,需要画点、线、面都是包含在两条语句中
glBegin
与glEnd
中,所画图形的不同都是通过设置glBegin中的参数来决定。
- 画点
GL_POINTS
示例 (所有代码展示皆为display中的语句)
glClearColor(0.0f, 0.0f, 0.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_POINTS);
glVertex2f(0.0f, 0.0f);
glVertex2f(0.5f, 0.5f);
glEnd();
glFlush();
效果
- 画线
GL_LINES
示例
glBegin(GL_LINES);
glVertex2f(0.0f, 0.0f);
glVertex2f(0.5f, 0.5f);
glEnd();
glFlush();
glClearColor(0.0f, 0.0f, 0.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
效果
除此之外还有
GL_LINE_STRIP(很多个点直接连接),GL_LINE_LOOP(收尾相连的闭合线),GL_TRIANGLES(绘制三角形),GL_TRIANGLE_STRIP(确保绘制的三角形都是同方向的),GL_TRIANGLE_FAN
等各种绘制方式。
区别2
- 画圆
static int n = 20;
static GLfloat R = 0.5;
static const GLfloat PI= 3.141592653;
void display(void) {
glClearColor(0.0f, 0.0f, 0.0f,0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBegin(GL_POLYGON);
for (int i = 0; i < n; i++) {
glVertex2f(R*cos(2 * PI / n * i), R*sin(2 * PI / n * i));
}
glEnd();
glFlush();
}
画圆
不填充注意到,这里使用了
GL_POLYGON
,这种绘图方式会将图形内部进行自动填充。如若使用GL_LINE_LOOP则会产生这种效果:
- 画正弦曲线
利用一定的数学公式,使用点与点直线相连的方式可画出各种各样的函数曲线
示例
void display(void) {
GLfloat x;
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_LINES);
glVertex2f(-1.0f, 0.0f);
glVertex2f(1.0f, 0.0f); // 以上两个点可以画x轴
glVertex2f(0.0f, -1.0f);
glVertex2f(0.0f, 1.0f); // 以上两个点可以画y轴
glEnd();
glBegin(GL_LINE_STRIP);
for (x = -1.0f / factor; x<1.0f / factor; x += 0.01f)
{
glVertex2f(x*factor, sin(x)*factor);
}
glEnd();
glFlush();
}
效果
image.png2. 关于点与直线
-
关于点
点的大小默认为1个像素,但也可以改变之。改变的命令为glPointSize,其函数原型如下:
void glPointSize(GLfloat size);
size必须大于0.0f,默认值为1.0f,单位为“像素”。
-
关于直线
(1)直线可以指定宽度:
void glLineWidth(GLfloat width);
其用法跟glPointSize类似。
(2)画虚线。
首先,使用glEnable(GL_LINE_STIPPLE)
;来启动虚线模式(使用glDisable(GL_LINE_STIPPLE)
可以关闭之)。
然后,使用glLineStipple来设置虚线的样式。
void glLineStipple(GLint factor, GLushort pattern);
pattern是由1和0组成的长度为16的序列,从最低位开始看,如果为1,则直线上接下来应该画的factor个点将被画为实的;如果为0,则直线上接下来应该画的factor个点将被画为虚的。
___示例
void display(void) {
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. 关于多边形的正反面
多边形在我们的二维坐标系中,我们一般把朝向我们的一面认为是正面,而把背朝着我们的一面认为是反面,在openGL中也存在着正反两面。接下来我们将通过一个示例,来讲解正反两面的写法与区别。
我们在进行绘制正反面之前,我们约定,逆时针方向绘制的面为正面,顺时针方向绘制的面为反面。我们通过
glFrontFace(GL_CCW); // 设置CCW方向为“正面”,CCW即CounterClockWise,逆时针
设置逆时针方向为正面。
为了体现出正反两面的区别,我们设置正面为填充模式,反面为线性绘制模式。接下来看我们的示例代码
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();
效果
- 剔除不必要的面
在三位绘图中,我们难免会遇到遮挡的问题,当我们面朝着正面的时候,反面难免会被遮挡而无法看到,所以这个时候我们就可以通过剔除来节约我们的计算空间。
首先需要通过glEnable(GL_GULL_FACE)
来允许剔除(可通过glDisable去除)
glCullFace的参数可以是GL_FRONT,GL_BACK或者GL_FRONT_AND_BACK,分别表示剔除正面、剔除反面、剔除正反两面的多边形。
在上面的代码中加上这两句
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
只剩下了反面的图形
剔除正面