OpenGL学习-------绘制简单的几何图形

本次课程所要讲的是绘制简单的几何图形,在实际绘制之前,让我们先熟悉一些概念。

一、点、直线和多边形
我们知道数学(具体的说,是几何学)中有点、直线和多边形的概念,但这些概念在计算机中会有所不同。
数学上的点,只有位置,没有大小。但在计算机中,无论计算精度如何提高,始终不能表示一个无穷小的点。另一方面,无论图形输出设备(例如,显示器)如何精确,始终不能输出一个无穷小的点。一般情况下,OpenGL中的点将被画成单个的像素(像素的概念,请自己搜索之~),虽然它可能足够小,但并不会是无穷小。同一像素上,OpenGL可以绘制许多坐标只有稍微不同的点,但该像素的具体颜色将取决于OpenGL的实现。当然,过度的注意细节就是钻牛角尖,我们大可不必花费过多的精力去研究“多个点如何画到同一像素上”。
同样的,数学上的直线没有宽度,但OpenGL的直线则是有宽度的。同时,OpenGL的直线必须是有限长度,而不是像数学概念那样是无限的。可以认为,OpenGL的“直线”概念与数学上的“线段”接近,它可以由两个端点来确定。
多边形是由多条线段首尾相连而形成的闭合区域。OpenGL规定,一个多边形必须是一个“凸多边形”(其定义为:多边形内任意两点所确定的线段都在多边形内,由此也可以推导出,凸多边形不能是空心的)。多边形可以由其边的端点(这里可称为顶点)来确定。(注意:如果使用的多边形不是凸多边形,则最后输出的效果是未定义的——OpenGL为了效率,放宽了检查,这可能导致显示错误。要避免这个错误,尽量使用三角形,因为三角形都是凸多边形)

可以想象,通过点、直线和多边形,就可以组合成各种几何图形。甚至于,你可以把一段弧看成是很多短的直线段相连,这些直线段足够短,以至于其长度小于一个像素的宽度。这样一来弧和圆也可以表示出来了。通过位于不同平面的相连的小多边形,我们还可以组成一个“曲面”。

二、在OpenGL中指定顶点
由以上的讨论可以知道,“点”是一切的基础。
如何指定一个点呢?OpenGL提供了一系列函数。它们都以glVertex开头,后面跟一个数字和1~2个字母。例如:
glVertex2d
glVertex2f
glVertex3f
glVertex3fv
等等。
数字表示参数的个数,2表示有两个参数,3表示三个,4表示四个(我知道有点罗嗦~)。
字母表示参数的类型,s表示16位整数(OpenGL中将这个类型定义为GLshort),
                   i表示32位整数(OpenGL中将这个类型定义为GLint和GLsizei),
                   f表示32位浮点数(OpenGL中将这个类型定义为GLfloat和GLclampf),
                   d表示64位浮点数(OpenGL中将这个类型定义为GLdouble和GLclampd)。
                   v表示传递的几个参数将使用指针的方式,见下面的例子。
这些函数除了参数的类型和个数不同以外,功能是相同的。例如,以下五个代码段的功能是等效的:
(一)glVertex2i(1, 3);
(二)glVertex2f(1.0f, 3.0f);
(三)glVertex3f(1.0f, 3.0f, 0.0f);
(四)glVertex4f(1.0f, 3.0f, 0.0f, 1.0f);
(五)GLfloat VertexArr3[] = {1.0f, 3.0f, 0.0f};
      glVertex3fv(VertexArr3);
以后我们将用glVertex*来表示这一系列函数。
注意:OpenGL的很多函数都是采用这样的形式,一个相同的前缀再加上参数说明标记,这一点会随着学习的深入而有更多的体会。

三、开始绘制
假设现在我已经指定了若干顶点,那么OpenGL是如何知道我想拿这些顶点来干什么呢?是一个一个的画出来,还是连成线?或者构成一个多边形?或者做其它什么事情?
为了解决这一问题,OpenGL要求:指定顶点的命令必须包含在glBegin函数之后,glEnd函数之前(否则指定的顶点将被忽略)。并由glBegin来指明如何使用这些点。
例如我写:

glBegin(GL_POINTS);
     glVertex2f(0.0f, 0.0f);
     glVertex2f(0.5f, 0.0f);
glEnd();

则这两个点将分别被画出来。如果将GL_POINTS替换成GL_LINES,则两个点将被认为是直线的两个端点,OpenGL将会画出一条直线。
我们还可以指定更多的顶点,然后画出更复杂的图形。
另一方面,glBegin支持的方式除了点GL_POINTS和线GL_LINES,还有平面带GL_LINE_STRIP,GL_LINE_LOOP,三角形GL_TRIANGLES,GL_TRIANGLE_STRIP,平面扇GL_TRIANGLE_FAN等,每种方式的大致效果见下图:

glBegin引用范例:

void myDisplay(void)
{
     glClear(GL_COLOR_BUFFER_BIT);
     glBegin( /* 在这里填上你所希望的模式 */ );
        /* 在这里使用glVertex*系列函数 */
        /* 指定你所希望的顶点位置 */
     glEnd();
     glFlush();
}

两个例子
例一、画一个圆
/*
正四边形,正五边形,正六边形,……,直到正n边形,当n越大时,这个图形就越接近圆,当n大到一定程度后,人眼将无法把它跟真正的圆相区别,这时我们已经成功的画出了一个“圆”
(注:画圆的方法很多,这里使用的是比较简单,但效率较低的一种)
试修改下面的const int n的值,观察当n=3,4,5,8,10,15,20,30,50等不同数值时输出的变化情况将GL_POLYGON改为GL_LINE_LOOP、GL_POINTS等其它方式,观察输出的变化情况

#include <math.h>
const int n = 20;
const GLfloat R = 0.5f;
const GLfloat Pi = 3.1415926536f;
void myDisplay(void)
{
     int i;
     glClear(GL_COLOR_BUFFER_BIT);
     glBegin(GL_POLYGON);
     for(i=0; i<n; ++i)
         glVertex2f(R*cos(2*Pi/n*i), R*sin(2*Pi/n*i));
     glEnd();
     glFlush();
}

例二、画一个五角星
/*
设五角星的五个顶点分布位置关系如下:
      A
E        B

D    C
首先,根据余弦定理列方程,计算五角星的中心到顶点的距离a(假设五角星对应正五边形的边长为.0)
a = 1 / (2-2*cos(72*Pi/180));
然后,根据正弦和余弦的定义,计算B的x坐标bx和y坐标by,以及C的y坐标
(假设五角星的中心在坐标原点)
bx = a * cos(18 * Pi/180);
by = a * sin(18 * Pi/180);
cy = -a * cos(18 * Pi/180);
五个点的坐标就可以通过以上四个量和一些常数简单的表示出来

#include <math.h>
const GLfloat Pi = 3.1415926536f;
void myDisplay(void)
{
     GLfloat a = 1 / (2-2*cos(72*Pi/180));
     GLfloat bx = a * cos(18 * Pi/180);
     GLfloat by = a * sin(18 * Pi/180);
     GLfloat cy = -a * cos(18 * Pi/180);
     GLfloat
         PointA[2] = { 0, a },
         PointB[2] = { bx, by },
         PointC[2] = { 0.5, cy },
         PointD[2] = { -0.5, cy },
         PointE[2] = { -bx, by };

     glClear(GL_COLOR_BUFFER_BIT);
     // 按照A->C->E->B->D->A的顺序,可以一笔将五角星画出
     glBegin(GL_LINE_LOOP);
         glVertex2fv(PointA);
         glVertex2fv(PointC);
         glVertex2fv(PointE);
         glVertex2fv(PointB);
         glVertex2fv(PointD);
     glEnd();
     glFlush();
}

关于glBegin的用法

OpenGL中的物体是用面边界模型来描述的。我们将物体表面分割成许多个平面,记录面的形状、颜色、纹理,OpenGL根据这些参数再把这些个面绘制出来,我们就能在场景中看到立体的实体了。

物体模型最基本的参数是它的形状,形状可以用表面来记录。而记录面的边缘就能描述面的形状。描述边缘的方法是记录边上所有线段的端点。所以用面边界模型描述物体形状的核心就是记录物体表面所有的顶点。这些顶点按所在边的顺序排列起来就能描述一个平面,许多的平面就能表示一个物体的表面,显然平面越多形状越逼真。

OpenGL中描述一个顶点的方法是指定其坐标和属性,命令是:

glVertex*(Coordination);

该命令以参数指定的坐标和当前颜色、纹理坐标、法向等属性定义一个顶点。

OpenGL中描述一个面的方法是glBegin/glEnd命令组:

glBegin(形状);
glVertex(顶点1);
glVertex(顶点2);
……
glEnd();

OpenGL支持点(GL_POINTS)、线段(GL_LINES)、三角形(GL_TRIANGLES)、四边形(GL_QUADS)、多边形(GL_POLYGON)。可以在一个begin/end对中定义多个同一类型的平面,如在glBegin(GL_TRIANGLES);与glEnd();之间输入11个顶点,则会形成3个三角形,最后两个顶点则被舍弃。

OpenGL还支持平面带(STRIP)和平面扇(FAN)。
扇:在glBegin(GL_TRIANGLE_FAN);/glEnd();间输入若干顶点,则第一个顶点做为共同的顶点,第二、三个做为底边定义一个三角形,此后的每个顶点与前一个顶点做为底边定义一个三角形,所以11个顶点就会定义9个共顶点的三角形,这些三角形将形成一个扇形。
带:输入顶点编号为123456789……;定义的三角形为132 243 354 465 567……,相邻三角形共用一条边,形成一条带状;依此类推,定义的四边形为1243 3465 5687……。
 

实际使用中,可用3ds max/softimage/maya之类的工具以直观的方式建立物体模型保存成文件,然后再用专门的解码工具将模型转换成一系列的顶点。解码工具有三类:插件、工具软件、程序库。目前已经有许多的代码库可以解析多种格式的三维场景,如果还没有合适的还也可以自己编写。

例三、画出正弦函数的图形
/*
由于OpenGL默认坐标值只能从-1到1,(可以修改,但方法留到以后讲)所以我们设置一个因子factor,把所有的坐标值等比例缩小,这样就可以画出更多个正弦周期试修改factor的值,观察变化情况

#include <math.h>
const GLfloat factor = 0.1f;
void myDisplay(void)
{
     GLfloat x;
     glClear(GL_COLOR_BUFFER_BIT);
     glBegin(GL_LINES);
         glVertex2f(-1.0f, 0.0f);
         glVertex2f(1.0f, 0.0f);         // 以上两个点可以画x轴
         glVertex2f(0.0f, -1.0f);
         glVertex2f(0.0f, 1.0f);         // 以上两个点可以画y轴
     glEnd();
     glBegin(GL_LINE_STRIP);
     for(x=-1.0f/factor; x<1.0f/factor; x+=0.01f)
     {
         glVertex2f(x*factor, sin(x)*factor);
     }
     glEnd();
     glFlush();
}

小结
本课讲述了点、直线和多边形的概念,以及如何使用OpenGL来描述点,并使用点来描述几何图形。
大家可以发挥自己的想象,画出各种几何图形,当然,也可以用GL_LINE_STRIP把很多位置相近的点连接起来,构成函数图象。如果有兴趣,也可以去找一些图象比较美观的函数,自己动手,用OpenGL把它画出来。

时间: 2024-10-04 03:23:07

OpenGL学习-------绘制简单的几何图形的相关文章

2.绘制简单的几何图形

一.点.直线和多边形 数学上的点,只有位置,没有大小.但在计算机中,无论计算精度如何提高,始终不能表示一个无穷小的点.另一方面,无论图形输出设备如何精确, 始终不能输出一个无穷小的点.一般情况下,OpenGL中的点将被画成单个的像素,虽然它可能足够小,但并不会是无穷小. 同一像素上,OpenGL可以绘制许多坐标只有稍微不同的点,但该像素的具体颜色将取决于OpenGL的实现. 同样的,数学上的直线没有宽度,但OpenGL的直线则是有宽度的.同时,OpenGL的直线必须是有限长度,而不是像数学概念那

IOS图像处理(1)绘制简单的几何图形

通过CoreGraphic绘制图像一般有以下几个步骤: 1:获取图形上下文对象 绘制图像首先需要取得图形上下文对象(CGContextRef),系统中维护一个CGContextRef的栈,在UI控件的drawRect方法调用前,系统会为当前绘图环境创建一个图形上下文对象并且置于CGContextRef栈顶,通过UIGraphicsGetCurrentContext()可以取得这个图像上下文对象. 2:设置绘画的属性,可以配置线条颜色,填充颜色,线条宽度,阴影,线段端点形状,点线模式,线条连接点风

OpenGL学习进程(4)第二课:绘制图形

本节是OpenGL学习的第二个课时,下面介绍如何用点和线来绘制图形:     (1)用点的坐标来绘制矩形: #include <GL/glut.h> void display(void) { // clear all pixels glClear(GL_COLOR_BUFFER_BIT); // draw yellow polygon (rectangle) with corners at glColor3f(1.0, 1.0, 0.0); glBegin(GL_POLYGON); //绘制开

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

    本节是OpenGL学习的第八个课时,下面将详细介绍OpenGL的颜色模式,颜色混合以及抗锯齿.     (1)颜色模式: OpenGL支持两种颜色模式:一种是RGBA,一种是颜色索引模式. RGBA模式与索引模式的区别: 计算机必须为每个像素保存一些数据,在RGBA模式中数据就代表了颜色:而颜色索引模式中数据代表了一个索引,要获取真正的颜色值还需要查索引表.数据的数量是由帧缓存中的位面决定的.一个位面为一个像素的一个位的数据.假如是8位面的颜色,每个像素就有8个颜色位,因此就有2的8次方

OpenGl学习进程(8)第六课:点、边和图形(三)绘制图形

本节是OpenGL学习的第六个课时,下面介绍OpenGL图形的相关知识:     (1)多边形的概念: 多边形是由多条线段首尾相连而形成的闭合区域.OpenGL规定,一个多边形必须是一个“凸多边形”.通过点.直线和多边形,就可以组合成各种几何图形.一段弧可以看成是是很多短的直线段相连,这些直线段足够短,以至于其长度小于一个像素的宽度.通过位于不同平面的相连的小多边形,还可以组成一个“曲面”. 什么是凸边形: 凸边形:多边形内任意两点所确定的线段都在多边形内,由此也可以推导出,凸多边形不能是空心的

OpenGL学习笔记3 —— 绘制3D物体、鼠标交互、反向变换

/* reference http://nehe.gamedev.net/article/using_gluunproject/16013/ */ #include <windows.h> // windows系统要加这个.因为下面2个头文件的一些宏是在这个文件中定义的 #include <gl/Gl.h> #include <gl/glut.h> //这两个头文件在OpenGL程序中几乎必加. #include <cstdio> //标准输入输出,用来打印

opengl使用现在比较常用的方法来绘制简单几何图元

上一篇文章中也使用了比较老的方法glBegin 和 glEnd的方法来绘制了简单的集合图元,现在使用比较新的而且更高效的方法来绘制简单的集合图元. 这种方法与以前方法的不同点在对数据的处理上,glBegin 和 glEnd是要给出数据,然后直接来进行绘制,然而新的方法是现将数据保存到显存中,然后直接一个绘制命令,就可以直接从显卡内存中直接读取数据进行绘制,效率更高而且更方便. #include <GL/glew.h> #include <GL/freeglut.h> #includ

opengl学习记录1——矩形绘制

1 #include <windows.h> 2 #include <gl/GL.h> 3 #include <gl/GLU.h> 4 #include <glut.h> 5 6 #pragma comment( lib, "glut.lib" ) 7 8 void display() 9 { 10 glClear( GL_COLOR_BUFFER_BIT ); 11 12 glColor3f( 1.0, 1.0, 1.0 ); 13 g

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

    本节是OpenGL学习的第七个课时,下面以四边形为例介绍绘制OpenGL动画的相关知识:     (1)绘制几种不同的四边形: 1)四边形(GL_QUADS) OpenGL的GL_QUADS图元用于绘制四边形,它根据每四个顶点绘制一个四边形. 注意:在使用四边形时必需记住四边形的四个角必须位于同一个平面中(不存在弯曲的四边形). 2)四边形带(GL_QUAD_STRIP) 该图元指定一个连接的四边形带.它们都保持相同方向的环绕. 3)通用多边形GL_POLYGON 我们可以用它绘制任意数