您的位置:首页 > 运维架构

第一个OpenGL程序

2017-12-22 20:39 477 查看

一、OpenGL简介

OpenGL基本函数库用来描述图元、属性、几何变换、观察变换和进行多种其它操作。

OpenGL是一个开放式的、与硬件无关的软件包。因此输入和输出函数等操作均不包含在其基本库中。但在OpenGL开发的辅助库中有输入和输出函数以及众多附加函数。

OpenGL是一个专业的、功能强大的、调用方便的底层三维图形函数库。

OpenGL是一个图形与硬件的接口。

二、OpenGl语法

OpenGl基本库(核心库)中的函数都要以gl为前缀。并把组成函数的每个单词首字母用大写形式表示。例如

glClear,glPolygonMode

OpenGL中的常量均以大写字母GL开头,命名中每一个组成单词均大写,中间用_隔开。例如

GL_RGB,GL_POLYGON

不同机器上整数描述范围可能不同,OpenGL有专门的数据类型。如下

后缀数据类型典型的对应C语言类型OpenGL类型定义
b8位整数signed charGLbyte
s16位整数shortGLshort
i32位整数int or longGLint,GLsizei
f32位浮点数floatGLfloat,GLclampf
d64位浮点数doubleGLdouble,GLclampd
ub8位无符号整数unsigned charGLubyte,GLboolean
us16位无符号整数unsigned shortGLushort
ui32位无符号整数unsigned int or unsigned longGLuint,GLenum,GLbitfield
OpenGL的库函数采用C语言风格,他们分别属于以下不同的库。

OpenGL核心库,函数名前缀gl。

OpenGL实用库,函数名前缀glu。

OpenGL辅助库,函数名前缀aux。

OpenGL工具库,函数名前缀glut。

Windows专用库,函数名前缀wgl。

Win32 API 函数库。

三、第一个OpenGL程序

首先一步步来创建我们的第一个OpenGL程序:在窗口中画一条线段。我们使用GLUT进行显示窗口管理。当使用OpenGL实用库时,首先要初始化GLUT,该初始化函数可以处理任何命令行变量,这里先不使用命令行参数。

glutInit(&argc, argv);

接着创建一个窗口并给出标题。

gultCreateWindow("LearnOpenGL example");

尽管窗口有默认位置和大小,但是还可以使用glut函数来设置这些参数。例如

glutInitWindowPosition(50,100);

上面代码指定显示窗口左上角应在屏幕左边界向右50个像素、屏幕上边界向下100个像素。

glutInitWindonSize(800,600);

上面代码指定宽度为800像素,高度为600像素的显示窗口。还可以使用
gultInitDisplayMode
函数来显示窗口和缓存和颜色模型。如下面使用单个缓存和RGB三原色组成的模型。

glutInitDisplayMode(GULT_SINGLE|GLUT_RGB);

可以使用RGB颜色设置显示窗口的背景颜色。使用函数

glClearColor(1.0,1.0,1.0,0.0);

上面代码将背景颜色设置为白色,四个参数是\(RGBA\),分别表示红、绿、蓝、以及调和参数,\(A=0.0\)表示完全透明,\(A=1.0\)表示完全不透明。这里先不仔细讨论这个参数。实验中我们将背景颜色设置为类似于黑板的颜色。

尽管上述命令将颜色参数赋给了窗口,但是不能让显示窗口在屏幕上出现。还必须引入下面函数

glClear(GL_COLOR_BUFFER_BIT);

变量
GL_COLOR_BUFFER_BIT
是OpenGL常量,用它来指定颜色缓存的位值。除了显示背景色,还可以为要显示的场景中的数据显示各种颜色。

glColor3f(0.0,0.4,0.2);

上面指定的三个分量就是RGB值。我们的第一个程序是显示一条二维的线段,但是OpenGL是默认处理3维的,二维线段是三维的特例,但是OpenGL还是采用三维观察来处理这个图形。用函数

glMatrixMode(GL_PROJECTTION);
gluOrtho2D(0.0,200.0,0.0,150.0);

表示用正投影观察将世界坐标系2维矩形区域映射到屏幕上,矩形区域上\(x\)范围从\(0-200.0\),\(y\)范围为\(0-150.0\)。完整程序

在OpenGL中,我们利用顶点来定义图形系统可以识别的基本几何图元。OpenGL中许多函数都有多重形式,顶点函数的形式为
glVertex*()
,*号表示诸如
nt、ntv
之类的,\(n\)代表维数,\(t\)表示数据类型,\(v\)表示变量由指向一个数组的指针来给出。例如在2维坐标中画一个点:
glVertex2f(50.0f,100.0f);
表示在二维坐标系中位置为\((50,100)\)处化一个点,点的数据类型是GLfloat,而下面形式用整数类型确定了三维空间的一个位置

glVertex3i(GLint x, GLint y,GLint z);

如果利用数组来表示三维点的信息
GLint vertex[3];
, 那么可以使用

glVertex3iv(vertex);

顶点可以定义很多位置的几何图元。下面是在窗口中画一条线段的完整程序。

#include <GL/glut.h>
#include <iostream>

using namespace std;

void lineSegment()
{
// clear display-window
glClear(GL_COLOR_BUFFER_BIT);
// set linesegment color to red
glColor3f(1.0, 0.0, 0.0);
// Create linesigment
glBegin(GL_LINES);
glVertex2i(0, 0);
glVertex2i(50, 500);
glEnd();

glFlush();
}

int main(int argc, char **argv)
{
// Initialize GLUT
glutInit(&argc, argv);
// Set display model
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
// Set window position
glutInitWindowPosition(100, 100);
// Set Display window size
glutInitWindowSize(800, 600);
//create aw window
glutCreateWindow("LearnOpenGL example");

// ====================================================================
// Set display-window color
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
// set projection parameters
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 200.0, 0.0, 200);

// display line
glutDisplayFunc(lineSegment);
glutMainLoop();
return 0;
}

OpenGL利用下面形式来定义几何对象

glBegin(type);
glVertex*();
...
...
glVertex*();
glEnd();

参数type指定OpenGL把顶点组合起来定义几何对象的方式。OpenGL提供了多种类型的点和线段图元

点(GL_POINTS) 每个顶点被显示的大小至少是一个像素。

线段(GL_LINES) 图元把相继的顶点配对后解释为线段的两个端点。注意顶点时两两配对处理的,所以如果有奇数个点,最后一个点由于无法配对,将会被舍弃。

折线(GL_LINE_STRIP,GL_LINE_LOOP) 使用这两个参数表示用线段将相邻两个点相连,而后者还将最后一个点与第一个点相连从而形成闭环。可以看经典教材《计算机图形学(第四版)》的\(P_{39}\)页更形象。

在绘制图元时,在应用程序结束后,可能我们还没来得及看到输出窗口就消失了。目前可以使用GLUT函数

void glutMainLoop();

这个函数执行会让程序进入一个事件处理循环。如果没有事件需要处理,程序会处于等待状态,直到通过某种外部方式来终止程序的执行,比如按下Ctrl+C。

图形是通过一个称为显示回调(display callback)的函数发送到屏幕上的。这个函数通过下面的GLUT函数指定并注册(register)到窗口系统:

void glutDisplayFunc(void (*func)(void));

只要窗口系统确定OpenGL窗口需要重新绘制,上面指定的func函数就会被调用。

四、动手实现二维Sierpinski镂垫程序

Sierpinski镂垫是一个有趣的图形。我们先来尝试绘制二维的Sierpinski镂垫图形,初始给出一个三角形ABC,步骤如下:

在三角形中随机选择一个初始点\(p(x,y)\).

随机选择三个顶点之一。

求点\(p\)与第二步中选择的三角形顶点的中点并将该点画出来。

更新该点为点\(p\)

转步骤2

我们假定循环5000次,然后看看最终的效果是什么。将主程序写成函数
display()
,先给出代码和效果,然后再对程序进行分析。

#include <GL/glut.h>
#include <iostream>
#include <cmath>
using namespace std;

void Init()
{
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glColor3f(1.0, 0.0, 0.0);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 100.0, 0.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}

void Display()
{
GLfloat vertices[3][2] = { {10.0,10.0},{90.0,10.0},{50.0, 70.0} };
int i, j, k;
GLfloat p[2] = { 75.0,75.0 };
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POINTS);
for (int i = 0; i < 5000; i++)
{
int j = rand() % 3;
p[0] = (vertices[j][0] + p[0]) / 2;
p[1] = (vertices[j][1] + p[1]) / 2;
glVertex2fv(p);
}
glEnd();
glFlush();
}

int main(int argc, char **argv)
{
// Initialize GLUT
glutInit(&argc, argv);
// Set display model
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
// Set window position
glutInitWindowPosition(100, 100);
// Set Display window size
glutInitWindowSize(800, 600);
//create aw window
glutCreateWindow("LearnOpenGL example");

// ====================================================================
// Set display-window color

// display Cycle
glutDisplayFunc(Display);

Init();
glutMainLoop();

return 0;
}

Init()
函数包括了必要的初始化步骤。主要看
display()
函数,我们首先定义了三角形的三个顶点存放在
vertices[]
数组中,然后在三角形内部随机选取了一个点p,接着就开始画点了,循环5000次,这个过程中,我们使用了
rand()
函数来随机选择一个三角形的顶点。而最终显示,这些点收敛的很有规律。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: