OpenGL完全教程 第三章 使用OpenGL绘图
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
procedure gluPerspective(fovy, aspect, zNear, zFar: GLdouble); 其中,fovy 为垂直方向上可见区域的角度(即上修剪平面和下修剪平面的二面角);
aspect 为高度与宽度的纵横比(即 Width/Height 的比值); zNear 和 zFar 为近、远修剪平面。 如图 3.1-7 所示。
private procedure SetView; procedure RenderScene; //渲染函数 procedure InitializeOpenGL; //用于初始化 OpenGL 渲染环境
public { public declarations }
end;
然后,在 FormCreate 过程中添加对过程 SetView 的调用:
图 3.1-4 平行投影下的甲烷分子模型 图 3.1-5 透视投影下的甲烷分子模型
值得注意的是,本节所讲的内容涉及矩阵变换这一主题。关于 OpenGL 中的矩阵,我们将在下一章中作具体说明。 因此本章不讨论矩阵变换的原理。
3.1.2.1 创建平行投影
调用 glOrtho 函数,可以创建一个平行投影:
也就是说,仅当顶点 v(x,y,z)满足条件 x>left and x
我们使用下面的代码创建一个平行投影:
glMatrixMode(GL_PROJECTION);
glOrtho(-ClientWidth div 2,ClientWidth div 2,-ClientHeight div 2,ClientHeight div 2,1,100);
图 3.1-7 由 gluPerspective 定义的平截头体 我们用下面的代码定义透视投影:
glMatrixMode(GL_PROJECTION);
gluPerspective(60,ClientWidth/ClientHeight,1,zFar);
glMatrixMode(GL_MODELVIEW);
图 3.1-1 WindowsGDI 下的窗体坐标 图 3.1-2 OpenGL 所定义的窗体坐标
例如,要设置如图 3.1-3 中的视见区域,我们应该调用函数: glViewPort(100,100,Width,Height);
图 3.1-3 3.1.2 创建投影变换
接下来,我们要设置一种投影变换。投影变换分为平行投影和透视投影。平行投影中,物体无论远近,大小都是 一样的,而透视投影则相反。因此,透视投影更像是我们眼睛所看到的景物。但在某些特殊的时候, 平行投影还是 有它的作用的,比如 3D 建摸程序。图 3.1-4 是甲烷分子模型在平行投影下的渲染结果,而图 3.1-5 是在透视投影下的 渲染结果。可以看到,平行投影下,四个氢原子(绿色的球体)大小是一样的,而在透视投影下,远处的氢原子要小一 些。
procedure FormCreate(Sender: TObject); begin
InitializeOpenGL; SetView; end;
我们的 SetView 过程看起来应该是这样的: procedure SetView; begin glClearColor(0,0,0,0);//设置背景颜色为黑色 glViewPort(0,0,ClientWidth,ClientHeight);//指定 OpenGL 在此区域内绘图。 glMatrixMode(GL_PROJECTION);//设置视图投影变换矩阵 glLoadIdentity;//加载单位矩阵。 glOrtho(0,ClientWidth,ClientHeight,0,1,-1);//创建平行投影空间。 glMatrixMode(GL_MODELVIEW);//将矩阵变换对象切换为模型视图变换。 end;
...图形绘制...
end;
3.1.5 整理代码
章节 3.1.1-3.1.3 中,所提到的所有代码在整个渲染流程中只需被执行一次。因此,我们可以向窗体添加一个过 程,将上述代码放到该过程中。并且在 OpenGL 初始化工作完毕之后执行它。
TfrmMain = class(TForm) ... procedure FormCreate(Sender: TObject);
• 设置可视区域并创建投影 • 在 3D 空间中绘制基本图元 • 使用深度测试 • 使用背面剔除提高渲染速度 • 将绘制的图形输出到屏幕上
3.1 绘制之前的必要工作
从章节 2.1 中,你应该了解到,在使用 OpenGL 绘图之前,我们应该决定使用何种投影方式,设置渲染后的图形 应出现在窗口的位置等等。本节中,我们将了解这些步骤的具体实现方法。 3.1.1 设置窗体的视见区域 (View Port)
点:GL_POINTS 线:GL_LINES 连续线:GL_LINE_STRIP 封闭线:GL_LINE_LOOP 值得说明的是图元 GL_LINE_STRIP 和 GL_LINE_LOOP。
GL_LINE_STRIP 和 GL_TRIANGLE_STRIP 原理是一样的。也就是从第 2 个顶点开始,第 n 个顶点与第 n-1 个顶点构 成一条直线。例如:
• 多边形
3.2.1 绘制三角形
绘制三角形是非常简单的。我们只需通过 glVertex 的调用传给 OpenGL 必要的顶点值即可。
在调用 glVertex 之前和之后,我们需要调用 glBegin 和 glEnd 这两个函数来标识图元的开始和结束。
在调用 glBegin 函数时,我们需要传入一个参数,以告诉 OpenGL 我们将绘制什么类型的图元。传入 GL_TRIANGLES 表明我们将要绘制三角形。例如:
3.2 使用 OpenGL 绘制基本图元
一切复杂的东西都是由简单而基本的元素构成的。在 OpenGL 中,组成复杂图形的基本元素被成为图元。掌握了 基本图元的绘制方法,就能绘制出任何复杂的物体。
OpenGL 为我们提供了以下几种图元:
•点
•线
• 连续线
• 封闭线
• 三角形
• 三角条形
• 三角扇形
• 四边形
glBegin(GL_LINE_STRIP);
glVertex(A.x,A.y,A.z);
glVertex(B.x,B.y,B.z);
glVertex(C.x,C.y,C.z);
glEnd;
将绘制出两条线段:线段 AB 和线段 BC。
图元 GL_LINE_LOOP 建立在 GL_LINE_STRIP 的基础 之上。与 GL_LINE_STRIP 不同的是,GL_LINE_LOOP 会在最后一 个顶点和第一个顶点之间再连一根直线,构成一个封闭图形。如果把上述代码的 GL_LINE_STRIP 参数该为 GL_LINE_LOOP,那么将绘制出三条线段:线段 AB、BC 和 CA。
在 OpenGL 初始化完成之后,我们应该进行一些视图设置。首先是设定视见区域,即告诉 OpenGL 应把渲染之后的 图形绘制在窗体的哪个部位。当视见区域是整个窗体时,OpenGL 将把渲染结果绘制到整个窗口。我们调用 glViewPort 函数来决定视见区域:
procedure glViewPort(x:GLInt;y:GLInt;Width:GLSizei;Height:GLSizei); 其中,参数 X,Y 指定了视见区域的左下角在窗口中的位置,一般情况下为(0,0),Width 和 Height 指定了视 见区域的宽度和高度。注意 OpenGL 使用的窗口坐标和 WindowsGDI 使用的窗口坐标是不一样的。图 3.1-1 表示了在 WindowsGDI 中的窗口坐标,而图 3.1-2 则是 OpenGL 所定义的窗口坐标。
OpenGL 完全教程 第三章 使用 OpenGL 绘图
作者:何咏 日期:2006-2-3 20:50:47 点击:3959
如需转载本文,请声明作者及出处。
第三章 使用 OpenGL 绘图
从本章开始,我们将正式开始使用 OpenGL 来绘制图形。学习本章内容,你将发现使用计算机绘制 3D 图形原来如 此容易。你将了解:
procedure glOrtho(left, right, bottom, top, zNear, zFar: GLdouble);
其中,left 指定了该平行投影最左边的平面; right 指定了该平行投影最右边的平面; bottom 指定了该平行投影最下边的平面; top 指定了该平行投影最上边的平面; zNear,zFar 指定了近修剪平面和远修建平面。
glVertex(1,0,1); glVertex(0,1,0); glVertex(1,1,0); glVertex(1,3,0); glVertex(4,8,2); glEnd; 3.2.3 绘制三角扇形 和绘制三角形相同,只要把 glBegin 的参数该为 GL_TRIANGLE_FAN 即可。由于绘制方法大致相同,这里不再举例 了。 3.2.4 绘制点、线、连续线、封闭线 下面列举了绘制这些图元应传给 glBegin 的值。
glMatrixMode(GL_MODELVIEW);
在上面的代码中,你看到了一个陌生的函数:glMatrixMode。它的作用是告诉 OpenGL 接下来我们将要设置投影 变换矩阵。这涉及到下一章的主题,这里就不多讨论了。现在你可以暂时把上面的代码当作固定代码使用。
3.1.2.2 创建透视投影
透视投影对远处的物体根据距离进行缩短或压缩变换。这使得远处的物体看起来小些,从而更加真实。因为远处 的景物更小,所以随着距离的增加,观察者应该能看到更多的景物。因此,透视投影的可视区域应是一个被称为平截 头体的几何形状。如图 3.1-6 所示。
其中,zFar 根据要绘制场景的大小设置百度文库同的值。
3.1.3 设置背景颜色
这一步是可选的。我们可以调用 glClearColor 函数来设置用于清空屏幕和缓冲区的颜色。
glClearColor(R,G,B,A:GLFloat);
其中,R,G,B,A 分别表示颜色的 R、G、B 分值和透明度值。取值范围均为 0-1 之间。例如,下面的代码把背景色设 置为黑色:
glClearColor(0,0,0,1);
3.1.4 绘制之前,清空屏幕和缓冲区
一般地,我们把所有绘制函数的调用写在 RenderScene 过程中。在每次绘制之前,我们都应该清空屏幕和缓冲区。 下面的代码用指定的清空颜色清空它们:
procedure RenderScene;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
3.2.5 绘制四边形和多边形
四边形(QUAD)也属于使用几率较高的图元。只要把 glBegin 的参数改为 GL_QUADS,就可以绘制四边形。把参数 改为 GL_POLYGON,则可以绘制一个多边形。
然而,仔细观察你将发现,无论是四边形还是多边形,只要花一点工夫,他们都可以使用三角形来表示。而且, 由于现在的显卡都对三角形的绘制做了大量的优化,使得绘制三角形的速度比绘制多边形的速度快得多。因此请尽量 不要使用多边形这种图元以提高渲染速度。
glBegin(GL_TRIANGLES); glVertex(1,0,1); glVertex(0,1,0); glVertex(1,1,0);
glEnd; 将绘制一个以点(1,0,1)、(0,1,0)、(1,1,0)为顶点的三角形。 3.2.2 绘制三角条形 和绘制三角形相同,只要把 glBegin 的参数该为 GL_TRIANGLE_STRIP 即可。例如: glBegin(GL_TRIANGLE_STRIP);
图 3.1-6 透视投影 和平行投影相似,只要把函数 glOrtho 的调用该为 glFustum 或者 gluPerspective。 调用 glFrustum 函数,可以指定一个平截头体。
procedure glFrustum (left, right, bottom, top, zNear, zFar: GLdouble); 可以看到,glFrustum 的参数和 glOrtho 完全一样。 但对于平截头体的性质来说,使用 glFrustum 总是不太直观。因此 gluPerspective 反而更常用:
aspect 为高度与宽度的纵横比(即 Width/Height 的比值); zNear 和 zFar 为近、远修剪平面。 如图 3.1-7 所示。
private procedure SetView; procedure RenderScene; //渲染函数 procedure InitializeOpenGL; //用于初始化 OpenGL 渲染环境
public { public declarations }
end;
然后,在 FormCreate 过程中添加对过程 SetView 的调用:
图 3.1-4 平行投影下的甲烷分子模型 图 3.1-5 透视投影下的甲烷分子模型
值得注意的是,本节所讲的内容涉及矩阵变换这一主题。关于 OpenGL 中的矩阵,我们将在下一章中作具体说明。 因此本章不讨论矩阵变换的原理。
3.1.2.1 创建平行投影
调用 glOrtho 函数,可以创建一个平行投影:
也就是说,仅当顶点 v(x,y,z)满足条件 x>left and x
我们使用下面的代码创建一个平行投影:
glMatrixMode(GL_PROJECTION);
glOrtho(-ClientWidth div 2,ClientWidth div 2,-ClientHeight div 2,ClientHeight div 2,1,100);
图 3.1-7 由 gluPerspective 定义的平截头体 我们用下面的代码定义透视投影:
glMatrixMode(GL_PROJECTION);
gluPerspective(60,ClientWidth/ClientHeight,1,zFar);
glMatrixMode(GL_MODELVIEW);
图 3.1-1 WindowsGDI 下的窗体坐标 图 3.1-2 OpenGL 所定义的窗体坐标
例如,要设置如图 3.1-3 中的视见区域,我们应该调用函数: glViewPort(100,100,Width,Height);
图 3.1-3 3.1.2 创建投影变换
接下来,我们要设置一种投影变换。投影变换分为平行投影和透视投影。平行投影中,物体无论远近,大小都是 一样的,而透视投影则相反。因此,透视投影更像是我们眼睛所看到的景物。但在某些特殊的时候, 平行投影还是 有它的作用的,比如 3D 建摸程序。图 3.1-4 是甲烷分子模型在平行投影下的渲染结果,而图 3.1-5 是在透视投影下的 渲染结果。可以看到,平行投影下,四个氢原子(绿色的球体)大小是一样的,而在透视投影下,远处的氢原子要小一 些。
procedure FormCreate(Sender: TObject); begin
InitializeOpenGL; SetView; end;
我们的 SetView 过程看起来应该是这样的: procedure SetView; begin glClearColor(0,0,0,0);//设置背景颜色为黑色 glViewPort(0,0,ClientWidth,ClientHeight);//指定 OpenGL 在此区域内绘图。 glMatrixMode(GL_PROJECTION);//设置视图投影变换矩阵 glLoadIdentity;//加载单位矩阵。 glOrtho(0,ClientWidth,ClientHeight,0,1,-1);//创建平行投影空间。 glMatrixMode(GL_MODELVIEW);//将矩阵变换对象切换为模型视图变换。 end;
...图形绘制...
end;
3.1.5 整理代码
章节 3.1.1-3.1.3 中,所提到的所有代码在整个渲染流程中只需被执行一次。因此,我们可以向窗体添加一个过 程,将上述代码放到该过程中。并且在 OpenGL 初始化工作完毕之后执行它。
TfrmMain = class(TForm) ... procedure FormCreate(Sender: TObject);
• 设置可视区域并创建投影 • 在 3D 空间中绘制基本图元 • 使用深度测试 • 使用背面剔除提高渲染速度 • 将绘制的图形输出到屏幕上
3.1 绘制之前的必要工作
从章节 2.1 中,你应该了解到,在使用 OpenGL 绘图之前,我们应该决定使用何种投影方式,设置渲染后的图形 应出现在窗口的位置等等。本节中,我们将了解这些步骤的具体实现方法。 3.1.1 设置窗体的视见区域 (View Port)
点:GL_POINTS 线:GL_LINES 连续线:GL_LINE_STRIP 封闭线:GL_LINE_LOOP 值得说明的是图元 GL_LINE_STRIP 和 GL_LINE_LOOP。
GL_LINE_STRIP 和 GL_TRIANGLE_STRIP 原理是一样的。也就是从第 2 个顶点开始,第 n 个顶点与第 n-1 个顶点构 成一条直线。例如:
• 多边形
3.2.1 绘制三角形
绘制三角形是非常简单的。我们只需通过 glVertex 的调用传给 OpenGL 必要的顶点值即可。
在调用 glVertex 之前和之后,我们需要调用 glBegin 和 glEnd 这两个函数来标识图元的开始和结束。
在调用 glBegin 函数时,我们需要传入一个参数,以告诉 OpenGL 我们将绘制什么类型的图元。传入 GL_TRIANGLES 表明我们将要绘制三角形。例如:
3.2 使用 OpenGL 绘制基本图元
一切复杂的东西都是由简单而基本的元素构成的。在 OpenGL 中,组成复杂图形的基本元素被成为图元。掌握了 基本图元的绘制方法,就能绘制出任何复杂的物体。
OpenGL 为我们提供了以下几种图元:
•点
•线
• 连续线
• 封闭线
• 三角形
• 三角条形
• 三角扇形
• 四边形
glBegin(GL_LINE_STRIP);
glVertex(A.x,A.y,A.z);
glVertex(B.x,B.y,B.z);
glVertex(C.x,C.y,C.z);
glEnd;
将绘制出两条线段:线段 AB 和线段 BC。
图元 GL_LINE_LOOP 建立在 GL_LINE_STRIP 的基础 之上。与 GL_LINE_STRIP 不同的是,GL_LINE_LOOP 会在最后一 个顶点和第一个顶点之间再连一根直线,构成一个封闭图形。如果把上述代码的 GL_LINE_STRIP 参数该为 GL_LINE_LOOP,那么将绘制出三条线段:线段 AB、BC 和 CA。
在 OpenGL 初始化完成之后,我们应该进行一些视图设置。首先是设定视见区域,即告诉 OpenGL 应把渲染之后的 图形绘制在窗体的哪个部位。当视见区域是整个窗体时,OpenGL 将把渲染结果绘制到整个窗口。我们调用 glViewPort 函数来决定视见区域:
procedure glViewPort(x:GLInt;y:GLInt;Width:GLSizei;Height:GLSizei); 其中,参数 X,Y 指定了视见区域的左下角在窗口中的位置,一般情况下为(0,0),Width 和 Height 指定了视 见区域的宽度和高度。注意 OpenGL 使用的窗口坐标和 WindowsGDI 使用的窗口坐标是不一样的。图 3.1-1 表示了在 WindowsGDI 中的窗口坐标,而图 3.1-2 则是 OpenGL 所定义的窗口坐标。
OpenGL 完全教程 第三章 使用 OpenGL 绘图
作者:何咏 日期:2006-2-3 20:50:47 点击:3959
如需转载本文,请声明作者及出处。
第三章 使用 OpenGL 绘图
从本章开始,我们将正式开始使用 OpenGL 来绘制图形。学习本章内容,你将发现使用计算机绘制 3D 图形原来如 此容易。你将了解:
procedure glOrtho(left, right, bottom, top, zNear, zFar: GLdouble);
其中,left 指定了该平行投影最左边的平面; right 指定了该平行投影最右边的平面; bottom 指定了该平行投影最下边的平面; top 指定了该平行投影最上边的平面; zNear,zFar 指定了近修剪平面和远修建平面。
glVertex(1,0,1); glVertex(0,1,0); glVertex(1,1,0); glVertex(1,3,0); glVertex(4,8,2); glEnd; 3.2.3 绘制三角扇形 和绘制三角形相同,只要把 glBegin 的参数该为 GL_TRIANGLE_FAN 即可。由于绘制方法大致相同,这里不再举例 了。 3.2.4 绘制点、线、连续线、封闭线 下面列举了绘制这些图元应传给 glBegin 的值。
glMatrixMode(GL_MODELVIEW);
在上面的代码中,你看到了一个陌生的函数:glMatrixMode。它的作用是告诉 OpenGL 接下来我们将要设置投影 变换矩阵。这涉及到下一章的主题,这里就不多讨论了。现在你可以暂时把上面的代码当作固定代码使用。
3.1.2.2 创建透视投影
透视投影对远处的物体根据距离进行缩短或压缩变换。这使得远处的物体看起来小些,从而更加真实。因为远处 的景物更小,所以随着距离的增加,观察者应该能看到更多的景物。因此,透视投影的可视区域应是一个被称为平截 头体的几何形状。如图 3.1-6 所示。
其中,zFar 根据要绘制场景的大小设置百度文库同的值。
3.1.3 设置背景颜色
这一步是可选的。我们可以调用 glClearColor 函数来设置用于清空屏幕和缓冲区的颜色。
glClearColor(R,G,B,A:GLFloat);
其中,R,G,B,A 分别表示颜色的 R、G、B 分值和透明度值。取值范围均为 0-1 之间。例如,下面的代码把背景色设 置为黑色:
glClearColor(0,0,0,1);
3.1.4 绘制之前,清空屏幕和缓冲区
一般地,我们把所有绘制函数的调用写在 RenderScene 过程中。在每次绘制之前,我们都应该清空屏幕和缓冲区。 下面的代码用指定的清空颜色清空它们:
procedure RenderScene;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
3.2.5 绘制四边形和多边形
四边形(QUAD)也属于使用几率较高的图元。只要把 glBegin 的参数改为 GL_QUADS,就可以绘制四边形。把参数 改为 GL_POLYGON,则可以绘制一个多边形。
然而,仔细观察你将发现,无论是四边形还是多边形,只要花一点工夫,他们都可以使用三角形来表示。而且, 由于现在的显卡都对三角形的绘制做了大量的优化,使得绘制三角形的速度比绘制多边形的速度快得多。因此请尽量 不要使用多边形这种图元以提高渲染速度。
glBegin(GL_TRIANGLES); glVertex(1,0,1); glVertex(0,1,0); glVertex(1,1,0);
glEnd; 将绘制一个以点(1,0,1)、(0,1,0)、(1,1,0)为顶点的三角形。 3.2.2 绘制三角条形 和绘制三角形相同,只要把 glBegin 的参数该为 GL_TRIANGLE_STRIP 即可。例如: glBegin(GL_TRIANGLE_STRIP);
图 3.1-6 透视投影 和平行投影相似,只要把函数 glOrtho 的调用该为 glFustum 或者 gluPerspective。 调用 glFrustum 函数,可以指定一个平截头体。
procedure glFrustum (left, right, bottom, top, zNear, zFar: GLdouble); 可以看到,glFrustum 的参数和 glOrtho 完全一样。 但对于平截头体的性质来说,使用 glFrustum 总是不太直观。因此 gluPerspective 反而更常用: