glBegin(mode_parameter);
glColor3f(r,g,b);
glVertex2f(x1,y2);
glVertex3f(x2,y2,z2);
glEnd();
这段代码的作用是在空间中以模式mode_parameter 和颜色(r g b) 在坐标(x1,y1,0.0)和(x2,y2,z2)处画两个点,当然你最终看到的是不是点还要取决于你的mode_parameter。在glbegin()与glend()之间是通过glvertex的一系列函数来定义一组顶点然后根据mode_parameter将这些点连接画线,或是以孤立点的形式画出,mode_parameter有以下几种:
GL_POINTS ,GL_LINES ,GL_LINE_STRIP ,GL_LINE_LOOP ,GL_TRIANGLES ,GL_TRIANGLE_STRIP ,GL_TRIANGLE_FAN ,GL_QUADS ,GL_QUAD_STRIP,GL_POLYGON
比较常用的是 GL_POINTS 画点 也就是说程序中以glvertex定义的点将被画在屏幕上
GL_LINES 画线 定义的每两个点将被连接起来变成一条直线,共N/2条
GL_LINE_STRIP 将所有的点连接变成一条折线
GL_LINE_LOOP 将GL_LINE_STRIP画成的折线头尾相连,形成闭合图形
GL_TRIANGLES 定义的每三个点将被连接起来涂成一个三角形,共N/3个
GL_QUADS 定义的每四个点将被连接起来涂成一个四边形,共N/4个
在这些模式中到底是哪几个点变成一组形成直线,或多边形取决于glvertex定义点的次序;数学上曲线是被定义为N个点连成的折线,当N趋向无穷大的情况。
2、要画一个园 不就是画一个正几百边形吗,这样我们就可以画出绝大多数简单的函数图形了,理论说完了来实践一下吧 :
void display()
{
glClearColor(1,1,1,1); //设置刷新背景色
glClear(GL_COLOR_BUFFER_BIT); //刷新背景
glBegin(GL_LINES); //画个十字充当坐标系
glColor3f(0,0,0); //设置当前颜色
glVertex3f(-1,0,0);
glVertex3f(1,0,0);
glVertex3f(0,-1,0);
glVertex3f(0,1,0);
glEnd();
glBegin(GL_LINE_STRIP); //画个y=sin(4x) 的函数图像
glColor3f(1,0,0);
for (float x=-1.00;x<=1.00;x+=0.01)
glVertex2f(x,sin(x*4*pi));
glEnd();
glBegin(GL_LINE_LOOP); //画个蓝色的单位圆
glColor3f(0,0,1);
for (float x=-1.00;x<=1.00;x+=0.01)
glVertex2f(x,sqrt(1-x*x));
for (float x=1.00;x>=-1.00;x-=0.01)
glVertex2f(x,-sqrt(1-x*x));
glEnd();
glFlush(); //更新窗口
}
这里glvertex2f(x,y) 等价与glvertex3f(x,y,0) 用这个display函数替换原来我们用来换背景的那个会看到一个单位圆,一个坐标系,和sin(4x)的图像
3、坐标变换 平移,缩放与旋转
前面我们知道OpenGL有内建的坐标系,事实上OpenGl有两套坐标系,一个坐标系被称为眼睛坐标(eye coordinate system) 简称ECS ,上章讲的就是这个坐标系。 OpenGL还有一套坐标,被称为(object coordinate system) 简称OCS ,而这个才是更为重要的,其实我们用来绘图的正是OCS。
两个坐标系中ECS 可以看成是一个现实存在的 基本不变的全局坐标系,而OCS则可以看成是用户自定义的坐标系,我们可以将这个坐标系任意的平移与缩放,在初始情况下他和ECS是重合的,也可以通过glLoadIdentity()强制复位,这样可以给我们的绘图带来极大的方便。这里有一点是要值得注意的是在使用一个函数时需要弄清它是使用什么坐标系的,刚刚我们用到的glVertex系列函数都是用的OCS
下面是一个平移的例子:
void makecross(float *color) //在当前OCS的中心画一个十字
{
glBegin(GL_LINES);
glColor3fv(color); //设置当前颜色
glVertex3f(-1,0,0);
glVertex3f(1,0,0);
glVertex3f(0,-1,0);
glVertex3f(0,1,0);
glEnd();
}
void display()
{
float red[3]={1,0,0};
float blue[3]={0,1,0};
float green[3]={0,0,1};
float yellow[3]={1,1,0};
glClearColor(1,1,1,1);
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
makecross(red);
glTranslatef(-0.5,-0.5,0);
makecross(blue);
glTranslatef(1,0.25,0);
makecross(green);
glTranslatef(-0.75,0.75,0);
glScalef(0.5,0.5,1); //在x,y 上缩小一半
makecross(yellow);
glFlush(); //更新窗口
}
这两个函数中makecross的作用是在坐标中心画一个十字,前面我们知道glVertex使用的是OCS 所以makecross 的作用便是在当前OCS的中心画一个十字,以观察OCS的位置,
glColor3fv(color)的功能于之前我们看到的glColor3f(r,g,b)是一样的,只不过一个是使用一个数组作为参数
void glLoadIdentity(void) 在display中 glLoadIdentity的作用是使OCS 与ECS 重合,在这里我们用来初始化OCS
void glTranslate{fd}(TYPEx, TYPE y, TYPEz); glTranslatef 是将OCS平移至x,y,z 出,也就是在(x,y,z)处建立新的OCS,这里要注意这里的参数X,Y,Z也是OCS坐标
void glScale{fd}(TYPEx, TYPE y, TYPEz); glScalef则是当前OCS的缩放,x,y,z 分别指在三个方向上的放大倍数
4、说完了缩放和平移,我们来看看旋转,opengl 里的旋转是通过glrotate来实现的,他的本质是将当前矩阵在乘于旋转矩阵,就是将当前的OCS 旋转一个指定的角度
void glRotate{fd}(TYPE angle, TYPE x, TYPE y, TYPE z); glrotate 是将当前OCS绕向量(x,y,z)逆时针旋转angle度 例如我们要讲上例中的图形旋转绕Z轴旋转45度则 可 以通过glrotatef(45,0,0,1)来实现。
5、glFlush()是OpenGL中的函数,用于强制刷新缓冲,保证绘图命令将被执行,而不是存储在缓冲区中等待其他的OpenGL命令;
glutSwapBuffers函数是OpenGL中GLUT工具包中用于实现双缓冲技术的一个重要函数。该函数的功能是交换两个缓冲区指针;
glFinish这是OpenGL的一个函数,用于向图形硬件提交缓冲区里的指令,并等待所有指令执行完成后再返回;