Win32 OpenGL编程(3) 基本图元(点,直线,多边

系统 1509 0

Win32 OpenGL 编程 ( 3 ) 基本图元(点,直线,多边形)的绘制

write by 九天雁翎 (JTianLing) -- blog.csdn.net/vagrxie

讨论新闻组及文件

一、 提要

在前面两篇相关文章

Win32 OpenGL 编程(1)Win32下的OpenGL编程必须步骤

Win32 OpenGL编程(2) 寻找缺失的OpenGL函数

中,我们已经建立了一个较为全面的 Win32 OpenGL 编程环境及一个简单的框架,并且,实际上掌握了 OpenGL Windows 下与 Win32 窗口交互的方法,在此基础上,总算是可以正式进行一些 OpenGL 相关知识的学习,前面的那些也就算是热身。本文的目的是将 OpenGL 中基本图元(点,线,多边形)的绘制大概的讲解一遍,最后可以组合的使用这些技术用 OpenGL 完成较为复杂的 2D 图形。

二、 基本图元相关概念

首先讲讲相关的概念,在 OpenGL 中,即使是复杂的图形,实际上也是由一些非常基本的图元组成,即点,直线,多边形,多边形中用的较多的又是三角形和矩形。在数学中,两点确定一条直线,三点确定一个三角形和一个面,同一个面上的四个点确定一个四边形。。。。。。在 OpenGL 中也大致的利用此方式来确定直线和多边形,也就是说,当你想画一个直线或者一个多边形的时候,只需要告诉 OpenGL 能确定此直线或者多边形的点即可。用参考 2 中的描述是:“在 OpenGL 中,所有的几何物体最终都描述成一组有序的顶点”。有此基本的概念后就可以看下面的例子了。

三、 OpenGL Hello World 示例分析

这里的 Hello World 程序指的是一个利用 OpenGL 完成的矩形绘制程序,相对于在系列文章 1 中的 Win32 OpenGL 编程框架,简化了很多东西,只剩下最最基本的 OpenGL 元素,但也是一个完善的 OpenGL 示例了。此示例显示的是一个白色的矩形,运行效果如附图 1 ,完整代码见我博客代码的 2009-10-12/SimpleRectangle 工程,具体下载及查看方法见本文最后的说明。

此示例 OpenGL 相关的主要就是两部分。

//OpenGL 初始化开始

void SceneInit ( int w , int h )

{

}

// 这里进行所有的绘图工作

void SceneShow ( GLvoid )

{

glClear ( GL_COLOR_BUFFER_BIT );

glBegin ( GL_QUADS );

glVertex3f (-0.5, -0.5, 0.0);

glVertex3f (0.5, -0.5, 0.0);

glVertex3f (0.5, 0.5, 0.0);

glVertex3f (-0.5, 0.5, 0.0);

glEnd ();

glFlush ();

}

我们下面从 OpenGL 的角度来分析此程序。作为 HelloWorld 级的程序,我简化了很多东西,首先 OpenGL 的初始化省略了,用的都是 OpenGL 的默认值,具体有哪些,后面一步一步说。以下是按步骤说明每个 OpenGL 函数。

1. glClear

OpenGL 参考手册 :

glClear takes a single argument that is the bitwise OR of several values indicating which buffer is to be cleared.

GL_COLOR_BUFFER_BIT Indicates the buffers currently enabled for color writing.

作用是清除颜色缓冲区。类似于我们使用一块新申请的内存时先用 memset/ZeroMemory 去清零一下,用这样的 Clear 操作为我们需要使用的颜色缓冲区 (Color Buffer) 清零一下。假如没有这样的操作,以前留在显存 / 内存 ( 不确定 ) 中的值会影响我们的操作,并且,这样的问题往往是非常难以调试和发现的,这一点大家可以尝试一下。

2. glBegin glEnd

OpenGL 参考手册 :

glBegin, glEnd - delimit the vertices of a primitive or a group of like primitives

OpenGL 代码的主体部分是:

glBegin ( GL_QUADS );

glVertex3f (-0.5, -0.5, 0.0);

glVertex3f (0.5, -0.5, 0.0);

glVertex3f (0.5, 0.5, 0.0);

glVertex3f (-0.5, 0.5, 0.0);

glEnd ();

glBegin glEnd 很明显是一对, 标志着一组 OpenGL 操作的开始和结束。 并且在参数中告诉了 OpenGL 下面的操作是针对什么图形进行的,此例中 GL_QUADS 是表示四边形。事实上还有很多其他的参数来表示各类图形,在《 OpenGL Programming Guide 》的 此页 Figure 2-7 : Geometric Primitive Types 一图形象的说明了各个参数的作用。

3. glVertex *

glVertex3f 就是在 基本图元相关概念 一节提到的 OpenGL 中确定顶点的函数。简而言之,上面的 4 glVertex3f 确定了矩形的 4 个顶点。(注意顺序)然后, OpenGL 就会自动根据 glBegin 指定的参数去完成相关的绘制任务了, 此例中 GL_QUADS 是表示四边形,所以最后的效果是一个矩形,实际的其他参数读者可以自己尝试一下。

4. OpenGL 默认坐标系

我们再看一下 glVertex* 指定顶点的代码:

glVertex3f (-0.5, -0.5, 0.0);

glVertex3f (0.5, -0.5, 0.0);

glVertex3f (0.5, 0.5, 0.0);

glVertex3f (-0.5, 0.5, 0.0);

为什么上述就指定了一个矩形的四个顶点呢?需要说明的是,在 OpenGL 中默认坐标体系与 Windows 中常用的不同, Windows 中常用的坐标体系(仅 2D )是用户区的左上角为坐标原点,即 (0.0,0.0) 点,右为坐标轴的 X 轴正方向,下为 Y 轴正方向, OpenGL 中的坐标轴( 3D )默认以客户区中心点为坐标原点( 0.0,0.0,0.0 ),右为坐标轴的 X 轴正方向,上为 Y 轴正方向,垂直指出屏幕的方向为 Z 轴正方向。长度定义是将客户区范围为按单位长度定义,即整个客户区恰好是 (-1,-1) (左下)到 (1,1) (右上)。附图 2 是一个上述示例程序附上 OpenGL 的平面坐标系的图,也可以作为 OpenGL 默认坐标系的参考图。

5. OpenGL 函数命名

这里顺面介绍一下 OpenGL 函数的命名规范,因为 C 语言天生的弱点及丰富的数据类型,在 OpenGL 中凡是牵涉到与参数数量和数据类型相关的函数,一般的命名方式都是 xxxx[n][t]

xxxx 表示函数的意义, [t] 用于表示此函数对应的类型。一般用单个的字母表示参数的类型, s 表示 16 位整数( OpenGL 中将这个类型定义为 GLshort ), i 表示 32 位整数( OpenGL 中将这个类型定义为 GLint GLsizei ), f 表示 32 位浮点数( OpenGL 中将这个类型定义为 GLfloat ), d 表示 64 位浮点数( OpenGL 中将这个类型定义为 GLdouble )。此例中使用的是 32 位浮点数,所以是 f 。这是 C 语言没有函数重载机制的天生弱点导致的扭曲应对方案。(用 C++ 就不需要这么麻烦了)

然后是数字,因为同样的原因,在 C 语言中一个同样意义的函数不能同时有不同个数的参数,所以 OpenGL 用一个数字来表示参数的个数,此例中是 3 ,表示以 3 个参数(即点的 X,Y,Z 坐标)来表示顶点。(事实上还有 glVertex2* glVertex4*

比如此例中,用如下代码效果是一样的:

glVertex2f (-0.5, -0.5);

glVertex2f (0.5, -0.5);

glVertex2f (0.5, 0.5) ;

glVertex2f (-0.5, 0.5);

glVertex2f 中, Z 轴默认为 0.

这里我依照参考 2 的用法,以 * 作为通配符来表示一组函数, * 既可以表示代表参数数量的数字也可以表示代表类型的字母。

6. glFlush

OpenGL 参考手册 :

glFlush - force execution of GL commands in finite time

说白了就是强制执行已经指定的 OpenGL 命令,与 fflush 命名类似作用也类似。

7. 小结

以上的 5 OpenGL 函数就构成了一个基本的 OpenGL 程序(不包括模板中使用的那些),由 glClear 清空颜色缓冲区获得干净的环境,由 glBegin 指定开始一组顶点操作的开始,并确认绘制图形,由 glVertex* 指定顶点,由 glEnd 表示操作结束,由 glFlush 强制开始绘图。运行效果如附图 1

四、 基本图元

事实上,上一节已经包含了所有的知识,各个图元在 OpenGL 中绘制方式的不同仅仅在于 glBegin 的参数不同而已,这里将基本图元简单介绍一下。

1.

点是最常用的图元之一了,而且所有的图像都可以看做是由点构成的,事实上屏幕也就是由一个一个像素点构成了图像:)

画点的方式是使用 GL_POINTS 为参数调用 glBegin 。那么,每一个 glVertex* 指定顶点就会绘制成一个单独的点。点的默认大小为 1 个像素,可以通过 glPointSize 函数来改变点的大小,在点比较大并且没有开启抗锯齿时,是按照一个正方形来绘制的。比如上例中,仅仅将 GL_QUADS 换成 GL_POINTS ,将是绘制上述矩形的 4 个顶点,为了截图效果显著,调用 glPointSize 将点的大小改为 20 。如下代码:

// 这里进行所有的绘图工作

void SceneShow ( GLvoid )

{

glClear ( GL_COLOR_BUFFER_BIT );

glPointSize (20);

glBegin ( GL_POINTS );

glVertex3f (-0.5, -0.5, 0.0);

glVertex3f (0.5, -0.5, 0.0);

glVertex3f (0.5, 0.5, 0.0);

glVertex3f (-0.5, 0.5, 0.0);

glEnd ();

glFlush ();

}

效果如附图 3 所示。

光是点也可以做很多有趣的应用, Windows 的屏保模拟星空即是其一,事实上,在原来学习简单的图形编程时,我用多种语言尝试了用点做一些有意思的东西。见简单图形编程学习系列:

简单图形编程的学习( 2 --- (Qt 实现 )

简单图形编程的学习( 2 --- (Windows GDI 实现 )

简单图形编程的学习( 2 --- (small basic 实现 )

其中点与文字结合形成的那个星空文字效果我是印象深刻,我一直将其作为“简单的编程技术 + 创意”也能很强大的例子。

2. 直线

直线也是很基础的东西了,但是 OpenGL 中的直线与数学概念上有些区别,不知道外国的那些专家在命名时为啥乱了,其实 OpenGL 中的直线与数学中的线段概念一致,有两个端点确认长度。事实上,在 OpenGL 绘制中,指定的也就是线段的两个端点。用 GL_LINES 调用 glBegin 时,表示绘制的是直线。默认情况下宽度为一个像素,同样, OpenGL 也提供了函数 glLineWidth 用以改变直线的宽度。比如上例中,仅仅将 GL_QUADS 换成 GL_LINES 将是两条平行的直线,并用 glLineWidth 将直线宽度改为 5 ,如下代码:

// 这里进行所有的绘图工作

void SceneShow ( GLvoid )

{

glClear ( GL_COLOR_BUFFER_BIT );

glLineWidth (5);

glBegin ( GL_LINES );

glVertex3f (-0.5, -0.5, 0.0);

glVertex3f (0.5, -0.5, 0.0);

glVertex3f (0.5, 0.5, 0.0);

glVertex3f (-0.5, 0.5, 0.0);

glEnd ();

glFlush ();

}

运行效果如附图 4 所示。

直线的应用也是非常广泛的,还记得 Windows 的屏保中的变幻线吗?千变万变,无论多么绚烂的效果,其实也仅仅是一条条变化的线段而已。

3. 多边形

其实可以将多边形看成是从点到线到面的一种扩展,这里的面自然也是有范围的,那么就成了多边形了,在绘制图形中用的最多的是三角形,因为三角形肯定在同一个面上,这样可以简化很多计算的处理。 GL_TRIANGLES 调用 glBegin 表示开始绘制三角形。然后还有 GL_QUADS 表示四边形(上例中的用法), GL_POLYGON 表示多边形(必须是凸的)。

4. 小结

其实除了上面讲到的那些参数,还有一些额外的参数,比如 GL_LINE_STRIP,GL_TRIANGLES_STRIP 等,表示绘制的时候绘制一些列连续的图形,这些参数用文字解释起来不够形象,还是推荐参考 OpenGL Programming Guide 》的 此页 Figure 2-7 : Geometric Primitive Types 一图,此图形象的展示了各个参数时对点的解释方式和顺序。在此图的下面,还有个表总结了一下各个参数的作用。

在一个 glBegin glEnd 对中可以连续的制定多个顶点,甚至超出你指定的图形的数目,比如绘制三角形时可以指定 6 个点,那么此时,将会绘制两个三角形而不是一个,这样而当指定 4 5 个点时用 GL_TRIANGLES 参数时将会丢弃,用 GL_TRIANGLE_STRIP 参数时将会连续绘制两个三角形,具体的解释方法也是要看 glBegin 参数的,建议还是参考上述图片。

五、 参考资料

1. OpenGL Reference Manual 》, OpenGL 参考手册

2. OpenGL 编程指南》(《 OpenGL Programming Guide 》), Dave Shreiner Mason Woo Jackie Neider Tom Davis 著,徐波译,机械工业出版社

3. Nehe OpenGL Tutorials 》, Nehe 著,在 http://nehe.gamedev.net/ 上可以找到教程及相关的代码下载,(有 PDF 版本教程下载) Nehe 自己还做了一个面向对象的框架,作为演示程序来说,这样的框架非常合适。也有 中文版 ,各取所需吧。

4. OpenGL 入门学习》 eastcowboy 著,这是我在网上找到的一个比较好的教程,较为完善,而且非常通俗。这是第一篇的地址: http://bbs.pfan.cn/post-184355.html

六、 系列其他文章

1. Win32 OpenGL 编程(1)Win32下的OpenGL编程必须步骤

2. Win32 OpenGL编程(2) 寻找缺失的OpenGL函数

七、 最后说明

本文中所有代码(如果有的话)都能用 Mercurial Google Code 中下载。

文章以博文发表的日期分目录存放,下载地址见:

http://code.google.com/p/jtianling/source/checkout?repo=blog-sample-code

或者直接使用 Mercurial 克隆下列库:

https://blog-sample-code.jtianling.googlecode.com/hg/

Mercurial 使用方法见《 分布式的,新一代 版本控制系统 Mercurial 的介绍及简要入门

八、 附图

1. 1 SimpleRectangle

Win32 OpenGL编程(3) 基本图元(点,直线,多边形)的绘制

图2 SimpleRectangle with coordinate

Win32 OpenGL编程(3) 基本图元(点,直线,多边形)的绘制

图3 SimplePoints

Win32 OpenGL编程(3) 基本图元(点,直线,多边形)的绘制

图4 SimpleLines

Win32 OpenGL编程(3) 基本图元(点,直线,多边形)的绘制

write by 九天雁翎 (JTianLing) -- blog.csdn.net/vagrxie

Win32 OpenGL编程(3) 基本图元(点,直线,多边形)的绘制


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论