openGl从零开始之基本图元

您所在的位置:网站首页 opengl设置正面颜色 openGl从零开始之基本图元

openGl从零开始之基本图元

2024-07-10 16:32| 来源: 网络整理| 查看: 265

一般情况 下,OpenGL 中的点将被画成单个的像素。实际上点还可以更小,虽然它可能足够小,但并不会是无穷小,一个像素内可以描绘多个点,取决于对点大小的设定,默认一个点的大小为一个像素。

当然我们也可以改变点的大小,函数原型为:

//size 必须大于 0.0f,默认值为 1.0f,单位为“像素”。 //对于具体的 OpenGL 实现,点的大小都有个限度的,如果设置的 size 超过最大值,则设置可能会有问题,一般情况是不在增大。 void glPointSize(GLfloat size);

代码实现画一个点,我们只需要在我们的绘图函数中添加如下代码即可:

void display(void) { glPointSize(5);//在绘制之前要设置要相关参数,这里设置点的大小为5像素 glBegin(GL_POINTS); { glVertex2f(0.0f, 0.0f); //OpenGl内的点是齐次坐标的四元组,缺省的z坐标为0.0f,w为1.0f,所以该点为(1, 2, 0, 1) glVertex2f(0.0f, 0.5f); //绘制的第二个点 glVertex2f(0.5f, 0.25f); //绘制的第三个点 } glEnd(); glFlush();//glFlush,保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待) }

需要注意的是:坐标的值默认是1.0为最大,即屏幕边缘,所以如果大于1,则会超出屏幕,这时候除非改变观察点,否则是看不到的。(0,0)表示在屏幕的中间,也就是坐标系原点。

OpenGL中绘制几何图元,必须使用 glBegain() 和 glEnd() 这一对函数,glBegin() 和 glEnd() 需要成对使用,两者之间是绘图语句。

glBegin()的参数就是需要绘制的图元类型,它决定了在glBegin()和glEnd()之间绘图的点将如何组织成目标图元,如参数为“GL_POINTS”,表示每一个点都是独立的,互不相连的,因此也就绘制出了一个个“点”。

2、线段

线段是由两个顶点连接起来形成的图元。线段间的连接方式有三种:

①独立线段:图元类型参数--GL_LINES

②线段间首尾相连但最终不闭合:折线,图元类型参数--GL_LINE_STRIP

③线段间首尾相连最终封口闭合:图形,图元类型参数--GL_LINE_LOOP

对应的图例:

 

线段代码实例:

void display(void) { /*同样用5个点,画出不同类型的线段组合*/ //独立线段,5个点能画出2条线段 glBegin(GL_LINES); { glVertex2f(-0.8f, -0.5f); glVertex2f(-0.5f, -0.5f); glVertex2f(-0.8f, 0.0f); glVertex2f(-0.5f, 0.0f); glVertex2f(-0.8f, 0.5f); //最后的这个点没有与之配对的点,无法连成线段,所以不会被画出来,在独立线段模式下被舍弃 } glEnd(); //连续不闭合折线,5个点能画出4条线段 glBegin(GL_LINE_STRIP); { glVertex2f(-0.3f, -0.5f); //起始点 //后面的每一个点都会与前一个相连生成一条线段 glVertex2f(-0.0f, -0.5f); glVertex2f(-0.3f, 0.0f); glVertex2f(-0.0f, 0.0f); glVertex2f(-0.3f, 0.5f); } glEnd(); //连续闭合折线,5个点能画出5条线段 glBegin(GL_LINE_LOOP); { glVertex2f(0.2f, -0.5f); //起始点 //后面的每一个点都会与前一个相连生成一条线段 glVertex2f(0.5f, -0.5f); glVertex2f(0.2f, 0.0f); glVertex2f(0.5f, 0.0f); //最后一个点不仅与前一个点相连,还与起始点相连,形成闭合 glVertex2f(0.2f, 0.5f); } glEnd(); glFlush();//保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待) }

程序运行示例图:

同样的,直线可以指定宽度:

void glLineWidth(GLfloat width); //width表示线宽,单位:像素

特殊的是线除了直线,还有虚线。可以用虚线连接两个点。

在绘制虚线之前必须先启动“虚线模式”:glEnable(GL_LINE_STIPPLE);

虚线有不同的类型,调节函数如下:

/* 参数pattern是16位二进制数(0或1),如OxAAAA表示1010101010101010 从低位开始,每一个二进制位代表一个像素, 1表示用当前颜色绘制一个像素,0表示当前不绘制,只移动一个像素位,中间留下一个像素的空白 factor是用来调节二进制位0和1代表的像素个数,如果factor为2,则表示遇到二进制1的时候用当前颜色绘制两个像素,0移动两个像素不绘制 */ void glLineStipple(GLint factor,GLushort pattern);

代码示例:

void display(void) { //开启虚线模式 glEnable(GL_LINE_STIPPLE); //调节虚线类型参数 glLineStipple(2,0xAAAA); //调节线宽 glLineWidth(3); //绘制一条虚线 glBegin(GL_LINES); { glVertex2f(0,0); glVertex2f(0.5,0.5); } glEnd(); glFlush();//保证前面的OpenGL命令立即执行(而不是让它们在缓冲区中等待) }

程序运行示例:

3、多边形

类似于点组合线段的方式,OpenGL定义的多边形是由多个点连接成线段再围成封闭区域。

多边形有两种:凸多边形(指多边形任意非相邻的两点的连线位于多边形的内部)和凹多边形,但OpenGL中规定的多边形必须是凸多边形。

但有时需要绘制一些凹多边形,通常解决的办法是对它们进行分割,用多个三角形来组合替代。显然,绘制这些三角形时,有些边不应该进行绘制,否则,多边形内部就会出现多余的线框。OpenGL提供的解决办法是通过设置边标志命令glEdgeFlag()来控制某些边产生绘制,而另外一些边不产生绘制,这里只需知道有这个工能,具体细节待遇到在研究,接下来看重点。

(1)连接方式

按点的定义顺序依次连接:图元类型参数--GL_POLYGON

从第1个点开始,每三个点一组画一个三角形,三角形之间是独立的:图元类型参数--GL_TRIANGLES

从第三个点开始,每点与前面的两个点组合画一个三角形,即线性连续三角形串:图元类型参数--GL_TRIANGLE_STRIP

从第三个点开始,每点与前一个点和第一个点组合画一个三角形,即扇形连续三角形:图元类型参数--GL_TRIANGLE_FAN

对应的图例:

 

四边形的绘制模式和三角形类似。

(2)多边形的正反两面

多边形为什么会有正反面这一说法呢?举个简单的例子。

虽然多边形是二维的,但是我们知道三维物体可以理解为多边形围成的,也就是说在三维空间物体上有二维多边形的存在。

一张“正方形”纸片,如果极限的薄,我们可以认为是一个多边形(正方形),那么纸仍然会存在两面,纸的正反面。更具体一点,如果我们用同大小6张正方形的纸片围成一个正方体,那么正方体的任何一个面都是一个多边形,而且这个多边形是有正反面,朝外的你能看到的部分是正面(假设),那么朝内的看不到的那部分就是反面。同样的道理,OpenGL要区分多边形的正反面。那么到底怎么定义正面或者反面呢?

有一个函数来定义:

glFrontFace(GL_CCW);//设置点序列逆时针方向围成的多边形为正面 glFrontFace(GL_CW); //设置点序列顺时针方向围成的多边形为正面

设置这个的原因是,默认情况下,OpenGL绘制三维物体时两面都会绘制,而实际的时候很多面我们是看不到的,如物体朝内方向的多边形,还有一些物体间遮挡的情况导致有些多边形是不可见的,因此为了提高性能,我们需要剔除这些不必要的绘制。

glEnable(GL_CULL_FACE); //来启动剔除功能 glCullFace(); //参数可以是GL_FRONT、GL_BACK、GL_FRONT_AND_BACK,表示剔除多边形的哪种面,设定后该类型的多边形不绘制 (3)绘制模式

常用的多边形绘制模式有:填充式(默认)、轮廓线式、顶点式和镂空图案填充式。

前三种都是使用glPolygonMode()函数来指定模式,最后一种比较特殊。

void glPolygonMode(GLenum face,GLenum mode);//该函数要求说明是对多边形哪一个面是定face设置模式

画一个多边形,设置不同的绘制模式,看一下效果:

代码:

void myDisplay(void) { //设置点的大小,以便容易观察 glPointSize(5); //设置正面的绘制模式为:填充式,反面不设定则默认为填充式 glPolygonMode(GL_FRONT,GL_FILL); glBegin(GL_POLYGON); { glVertex2f(0,0); glVertex2f(0,0.3); glVertex2f(-0.3,0.3); glVertex2f(-0.3,0); } glEnd(); //设置正面的绘制模式为:轮廓线式 glPolygonMode(GL_FRONT,GL_LINE); glBegin(GL_POLYGON); { glVertex2f(0.5,0); glVertex2f(0.5,0.3); glVertex2f(0.2,0.3); glVertex2f(0.2,0); } glEnd(); //设置正面的绘制模式为:顶点式 glPolygonMode(GL_FRONT,GL_POINT); glBegin(GL_POLYGON); { glVertex2f(0.9,0); glVertex2f(0.9,0.3); glVertex2f(0.6,0.3); glVertex2f(0.6,0); } glEnd(); glFlush(); }

示例图:

关于最后一种镂空图案样式,有点类似于线段中的虚线,这里只不过是针对多边形内部区域进行像素点的绘制与否,来做镂空效果。具体的细节还需查阅资料。

 

以上为基本图元的知识讲解,并给出了针对性的代码实例,在此基础之上会进一步学习更加复杂的图形绘制。

 

 



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3