zoukankan      html  css  js  c++  java
  • 第一个OpenGL程序

    一、OpenGL简介

    • OpenGL基本函数库用来描述图元、属性、几何变换、观察变换和进行多种其它操作。
    • OpenGL是一个开放式的、与硬件无关的软件包。因此输入和输出函数等操作均不包含在其基本库中。但在OpenGL开发的辅助库中有输入和输出函数以及众多附加函数。
    • OpenGL是一个专业的、功能强大的、调用方便的底层三维图形函数库。
    • OpenGL是一个图形与硬件的接口。

    二、OpenGl语法

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

    glClear,glPolygonMode
    

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

    GL_RGB,GL_POLYGON
    

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

    后缀 数据类型 典型的对应C语言类型 OpenGL类型定义
    b 8位整数 signed char GLbyte
    s 16位整数 short GLshort
    i 32位整数 int or long GLint,GLsizei
    f 32位浮点数 float GLfloat,GLclampf
    d 64位浮点数 double GLdouble,GLclampd
    ub 8位无符号整数 unsigned char GLubyte,GLboolean
    us 16位无符号整数 unsigned short GLushort
    ui 32位无符号整数 unsigned int or unsigned long GLuint,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,步骤如下:

    1. 在三角形中随机选择一个初始点(p(x,y)).
    2. 随机选择三个顶点之一。
    3. 求点(p)与第二步中选择的三角形顶点的中点并将该点画出来。
    4. 更新该点为点(p)
    5. 转步骤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()函数来随机选择一个三角形的顶点。而最终显示,这些点收敛的很有规律。

  • 相关阅读:
    vue中computed和watch的区别,以及适用场景
    vue中使用过的全局API
    厦门中控
    设置圆角的弧度,保持兼容性
    伪元素::after和::before
    SpringMVC
    mui问题
    错误记录
    Android错误
    Android之界面(布局文件layput)
  • 原文地址:https://www.cnblogs.com/tandier/p/8087557.html
Copyright © 2011-2022 走看看