从本篇開始,会给出一些代码实例,所以要配置好编译环境。

环境配置:

vs2012下配置链接http://www.cnblogs.com/dreampursuer/archive/2014/05/27/3754528.html

vc++6.0下配置链接http://blog.csdn.net/hbuxiaoshe/article/details/5047564

在给出详细的画图代码之前,先解说一下创建一个openGl程序窗体的初始化,在上一篇文章里已经介绍了,这里再贴一遍。

void display(void)
{
//这是我们自己的画图函数。我们在这里进行详细地绘制。 } int main(int argc, char** argv)
{
glutInit(&argc, argv); //对GLUT进行初始化,必须一開始就初始化
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); //设置显示方式。參数之后再解释
glutInitWindowPosition(100, 100); //设置程序窗体在屏幕中的位置
glutInitWindowSize(400, 400); //设置程序窗体的大小
glutCreateWindow("第一个OpenGL程序"); //给程序窗体加入标题 glutDisplayFunc(&display); //*调用我们自己的画图函数来绘制
glutMainLoop(); //启动消息循环后程序执行起来 return 0;
}

OpenGL的基本图元有点(Point)、线段(Line)、多边形(Ploygon)、三角形(Triangle)、四边形(Quadrangle)。组成关系我想大部分人都可以理解:

  ①无数个“点”的线性排列组成----“线段”

  ②多个“线段”能够围成一个“多边形”

  ③多个“多边形”在三维空间中能够围成“多面体”

有此,能够看出,点是最主要的图元,其它的图元都是由顶点组合构成的。因此我们从点開始介绍。

1、点

在OpenGL中,“点”称为顶点(Vertex),通经常使用一个形如(x, y, z)的三维坐标值表示。

有时候会採用齐次坐标表示。就是一个形如(x, y, z, w)的四元组,能够这样理解这个四元组。前面的(x,y,z)表示“点”所在的方向。而w表示在该方向上的距离比例。所以(x, y, z, w)表示的实际坐标值就是(x/w, y/w, z/w)坐标点。假设w为0。则表示方向为(x, y, z)的无穷远点;假设w=10,表示取(x,y,z)的十分之中的一个作为坐标点(x/10,y/10,z/10)。

普通情况 下,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,所以该点为(0, 0, 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)连接方式

<1>按点的定义顺序依次连接:图元类型參数--GL_POLYGON

<2>从第1个点開始。每三个点一组画一个三角形,三角形之间是独立的:图元类型參数--GL_TRIANGLES

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

<4>从第三个点開始,每点与前一个点和第一个点组合画一个三角形。即扇形连续三角形:图元类型參数--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)
{
//设置点的大小,以便easy观察
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();
}

演示样例图:

关于最后一种镂空图案样式,有点类似于线段中的虚线,这里仅仅只是是针对多边形内部区域进行像素点的绘制与否。来做镂空效果。

详细的细节还需查阅资料。

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

openGl学习之基本图元的更多相关文章

  1. OpenGL学习进程(11)第八课:颜色绘制的详解

        本节是OpenGL学习的第八个课时,下面将详细介绍OpenGL的颜色模式,颜色混合以及抗锯齿.     (1)颜色模式: OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. R ...

  2. OpenGL学习之路(一)

    1 引子 虽然是计算机科班出身,但从小对几何方面的东西就不太感冒,空间想象能力也较差,所以从本科到研究生,基本没接触过<计算机图形学>.为什么说基本没学过呢?因为好奇(尤其是惊叹于三维游戏 ...

  3. OpenGL学习之路(三)

    1 引子 这些天公司一次次的软件发布节点忙的博主不可开交,另外还有其它的一些事也占用了很多时间.现在坐在电脑前,在很安静的环境下,与大家分享自己的OpenGL学习笔记和理解心得,感到格外舒服.这让我回 ...

  4. OpenGL学习之路(四)

    1 引子 上次读书笔记主要是学习了应用三维坐标变换矩阵对二维的图形进行变换,并附带介绍了GLSL语言的编译.链接相关的知识,之后介绍了GLSL中变量的修饰符,着重介绍了uniform修饰符,来向着色器 ...

  5. OpenGL学习进程(10)第七课:四边形绘制与动画基础

        本节是OpenGL学习的第七个课时,下面以四边形为例介绍绘制OpenGL动画的相关知识:     (1)绘制几种不同的四边形: 1)四边形(GL_QUADS) OpenGL的GL_QUADS图 ...

  6. OpenGL学习进程(7)第五课:点、边和图形(二)边

    本节是OpenGL学习的第五个课时,下面介绍OpenGL边的相关知识: (1)边的概念: 数学上的直线没有宽度,但OpenGL的直线则是有宽度的.同时,OpenGL的直线必须是有限长度,而不是像数学概 ...

  7. OpenGL学习进程(6)第四课:点、边和图形(一)点

    本节是OpenGL学习的第四个课时,下面介绍OpenGL点的相关知识:     (1)点的概念:     数学上的点,只有位置,没有大小.但在计算机中,无论计算精度如何提高,始终不能表示一个无穷小的点 ...

  8. OpenGL ES 3.0: 图元重启(Primitive restart)

    [TOC] 背景概述 在OpenGL绘制图形时,可能需要绘制多个并不相连的图形.这样的情况下这几个图形没法被当做一个图形来处理.也就需要多次调用 DrawArrays 或 DrawElements. ...

  9. OpenGL学习笔记3——缓冲区对象

    在GL中特别提出了缓冲区对象这一概念,是针对提高绘图效率的一个手段.由于GL的架构是基于客户——服务器模型建立的,因此默认所有的绘图数据均是存储在本地客户端,通过GL内核渲染处理以后再将数据发往GPU ...

随机推荐

  1. 如何解决数据库中,数字+null=null

    如何解决数据库中,数字+null=null 我使用SQLServer,做一个 update 操作,累计一个数.在数据库中,为了方便,数据库中这个字段我设为允许为空,并且设置了默认值为 0 .但是在新增 ...

  2. golang 自定义time.Time json输出格式

    工作中使用golang时,遇到了一个问题.声明的struct含time.Time类型.使用json格式化struct时,time.Time被格式化成”2006-01-02T15:04:05.99999 ...

  3. 【笔记JS/HTML/CSS】CSS3实现鼠标滑动显示动画(transition、transform)

    内容中包含 base64string 图片造成字符过多,拒绝显示

  4. position的简单用法实例 ----- 方框里图片放对应的角标

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...

  5. git学习(2)----入门

    一.git.github和gitlab的区别 Git诞生于2005年,大神Linus的作品,Github诞生于2008年,没有Git就没有GitHub,Github已成为全球最大的代(tong)码(x ...

  6. 洛谷——P2420 让我们异或吧

    P2420 让我们异或吧 题目描述 异或是一种神奇的运算,大部分人把它总结成不进位加法. 在生活中…xor运算也很常见.比如,对于一个问题的回答,是为1,否为0.那么: (A是否是男生 )xor( B ...

  7. 使用 MyBatis 对表执行 CRUD 操作

    说明: 1.CRUD: C --  create    R -- read   U -- update  D -- delete 2.Mybatis 的 SQL 核心配置文件中 SQL 语句的参数的传 ...

  8. 基于服务器版centos7的Hadoop/spark搭建

    前提说明: 1.Hadoop与spark是两个独立的框架,只安装spark也可独立运行,spark有自己的调度器(standalone模式): 2.在Hadoop的基础上安装spark就是为了使用ya ...

  9. Greek symbols --Latex

    $\propto$     \propto $\infty$   \infty $\ne$   \ne $\approx$     \approx $\sim$ :    \sim  --- same ...

  10. BZOJ 1468 Tree 【模板】树上点分治

    #include<cstdio> #include<algorithm> #define N 50010 #define M 500010 #define rg registe ...