OpenGL一个简单的例子

合集下载

opengl学习(三)----绘制简单图形(一)

opengl学习(三)----绘制简单图形(一)

opengl学习(三)----绘制简单图形(⼀)今天说⼀说⼏种简单的图元。

所有的⼏何图元都是根据它们的顶点来描绘的。

⽽顶点就是它们在屏幕上的坐标位置。

我喜欢把这⼏个简单的图元称为点线⾯。

点,可以看到⼀个顶点;线,就是两个顶点指定的⼀条有限长度的线段;⾯,其实更准确讲是⼀个凸多边形。

opengl⾥所讲的多边形是内部⽤颜⾊填充的,视觉上称为⾯我个⼈认为是更贴近的。

当然,多边形也是由指定的顶点组成的。

需要注意的是,要想被opengl按照设计被绘制必须正确的认识到,所谓的多边形是顶点都处于⼀个平⾯上,凸多边形。

凸多边形不能理解的,请问度娘。

来看⼀个例⼦:C++代码1. glBegin(GL_POLYGON);2. glVertex2f(0.0, 0.0);3. glVertex2f(0.0, 3.0);4. glVertex2f(4.0, 3.0);5. glVertex2f(6.0, 1.5);6. glVertex2f(4.0, 0.0);7. glEnd();先不去关⼼代码本⾝,这段代码最终的结果是要指定5个顶点绘制⼀个凸五边形。

注意,不是5条线段⽽是⼀个凸五边形的平⾯。

不管是点线⾯的哪⼀种,都是需要指定⼀组顶点的。

如何判定顶点指定的开始和结束就是glBegin和glEnd的⼯作。

引⽤void glBegin(Glenum mode);标志着⼀个顶点数据列表的开始,它描述了⼀个⼏何图元。

mode参数指定了图元的类型。

void glEnd(void);标志着⼀个顶点数据列表的结束。

mode设置的不同,代表着将要绘制的图元也不同。

下⾯这个表就是图元的名称和含义:值含义GL_POINTS 单个的点GL_LINES ⼀对顶点被解释为⼀条直线GL_LINE_STRIP ⼀系列的连接直线GL_LINE_LOOP 和上⾯相同,但第⼀个顶点和最后⼀个顶点彼此相连GL_TRIANGLES 3个顶点被解释为⼀个三⾓形GL_TRIANGLES_STRIP 三⾓形的连接串GL_TRIANGLES_FAN 连接成扇形的三⾓形系列GL_QUADS 4个顶点被解释为⼀个四边形GL_QUADS_STRIP 四边形的连接串GL_POLYGON 简单的凸多边形的边界试想着,如果将glBegin(GL_POLYGON)修改为glBegin(GL_POINTS),绘制出来的将是什么图形呢? 哈哈,那就是5个点⽽已么。

OpenGL纹理贴图简单例子

OpenGL纹理贴图简单例子

【代码】#include<windows.h>#include<GL/glut.h>#include<GL/glext.h>staticdoubleX = 0;staticdoubleY = 0;staticdoubleZ = 7;//定义函数指针,在Windows环境下使用OpenGL扩展PFNGLACTIVETEXTUREARBPROC glActiveTextureARB = NULL; PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB = NULL; //纹理存储数组staticGLubyte T0[64][64][4];staticGLubyte T1[64][64][4];staticGLubyte T2[64][64][4];//纹理名字staticGLuint Tname0;staticGLuint Tname1;staticGLuint Tname2;//创建纹理voidmakeImages(){//第二个纹理,黑白相间横条,*64for(i = 0; i < 64; i++) {for(j = 0; j < 64; j++) {if(i % 16 < 8) c = 255;//第一个纹理,渐变绿色,*64for(i = 0; i < 64; i++) {}for(j = 0; j < 64; j++) {}T0[i][j][0] = (GLubyte) 0;T0[i][j][1] = (GLubyte) i * 5 + j * 5;T0[i][j][2] = (GLubyte) 0;T0[i][j][3] = (GLubyte) 255;inti, j, c;}}}elsec = 0;T1[i][j][0] = (GLubyte) c;T1[i][j][1] = (GLubyte) c;T1[i][j][2] = (GLubyte) c;T1[i][j][3] = (GLubyte) 255;//第三个纹理,黑白相间竖条,*64 for(i = 0; i < 64; i++) {}for(j = 0; j < 64; j++) {}if(j % 16 < 8) c = 255;elsec = 0;T2[i][j][0] = (GLubyte) c;T2[i][j][1] = (GLubyte) c;T2[i][j][2] = (GLubyte) c;T2[i][j][3] = (GLubyte) 255;voidinit(){//初始化纹理glBindTexture(GL_TEXTURE_2D, Tname0);//生成指定名字的纹理对象glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA,GL_UNSIGNED_BYTE, T0);//设glGenTextures(1, &Tname0);//获取纹理名字glGenTextures(1, &Tname1);//获取纹理名字glGenTextures(1, &Tname2);//获取纹理名字makeImages();//纹理初始化glPixelStorei(GL_UNPACK_ALIGNMENT, 1);//对其像素字节//场景初始化glClearColor (0.0,0.0,0.0,0.0);glShadeModel(GL_FLAT);glEnable(GL_DEPTH_TEST);//获取函数地址glActiveTextureARB =glMultiTexCoord2fARB =(PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");(PFNGLMULTITEXCOORD2FARBPROC)wglGetProcAddress("glMultiTexCoord2fAR B");置纹理对象内容}voiddisplay(){//绘制正方形glBegin(GL_QUADS);glMultiTexCoord2fARB (GL_TEXTURE0_ARB,0.0,0.0);glVertex3f(-4.0,1.5,0.0);glMultiTexCoord2fARB (GL_TEXTURE0_ARB,0.0,1.0);glVertex3f(-4.0,3.5,0.0);glMultiTexCoord2fARB (GL_TEXTURE0_ARB,1.0,1.0);glVertex3f(-2.0,3.5,0.0);glMultiTexCoord2fARB (GL_TEXTURE0_ARB,1.0,0.0);//激活纹理对象glActiveTextureARB (GL_TEXTURE0_ARB);//选中号纹理glEnable(GL_TEXTURE_2D);//使纹理可用glBindTexture(GL_TEXTURE_2D, Tname0);//激活纹理glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);//设置纹理贴图方式glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glLoadIdentity();gluLookAt((GLfloat)X, (GLfloat)Y, (GLfloat)Z,0.0,0.0,0.0,0.0,1.0,0.0);//视图变换glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//设置纹理过滤方式glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT);//设置纹理过滤方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//设置纹理过滤方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_LINEAR);//设置纹理过滤方式//同上,初始化纹理glBindTexture(GL_TEXTURE_2D, Tname1);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA,GL_UNSIGNED_BYTE, T1);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//同上,初始化纹理glBindTexture(GL_TEXTURE_2D, Tname2);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 64, 64, 0, GL_RGBA,GL_UNSIGNED_BYTE, T2);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glVertex3f(-2.0,1.5,glEnd();glDisable(GL_TEXTURE_2D);//同上,绘制正方形,使用号纹理glActiveTextureARB (GL_TEXTURE1_ARB);glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, Tname1);glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBegin(GL_QUADS);glMultiTexCoord2fARB (GL_TEXTURE1_ARB,0.0,0.0);glVertex3f(-1.0,1.5,0.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB,0.0,1.0);glVertex3f(-1.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB, 1.0,1.0);glVertex3f(1.0,3.5,0.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB, 1.0,0.0);glVertex3f(1.0,1.5,0.0);glEnd();glDisable(GL_TEXTURE_2D);//同上,绘制正方形,使用号纹理glActiveTextureARB(GL_TEXTURE2_ARB); glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, Tname2);glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBegin(GL_QUADS);glMultiTexCoord2fARB (GL_TEXTURE2_ARB,0.0,0.0);glVertex3f(2.0,1.5,0.0);glMultiTexCoord2fARB (GL_TEXTURE2_ARB,0.0,1.0);glVertex3f(2.0,3.5,0.0);glMultiTexCoord2fARB (GL_TEXTURE2_ARB,1.0,1.0);glVertex3f(4.0,3.5,0.0);glMultiTexCoord2fARB (GL_TEXTURE2_ARB,1.0,0.0);glVertex3f(4.0,1.5,0.0);glEnd();glDisable(GL_TEXTURE_2D);//同上,绘制正方形,使用号和号纹理glActiveTextureARB (GL_TEXTURE0_ARB);glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, Tname0);glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glActiveTextureARB (GL_TEXTURE1_ARB);glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, Tname1);glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);glBegin(GL_QUADS);glMultiTexCoord2fARB (GL_TEXTURE0_ARB, 0.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB, 0.0,0.0);glVertex3f(-2.5, -1.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE0_ARB,0.0,1.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB,0.0,1.0);glVertex3f(-2.5,1.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE0_ARB, 1.0,1.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB, 1.0,1.0);glVertex3f(-0.5,1.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE0_ARB, 1.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB, 1.0,0.0);glVertex3f(-0.5, -1.0,0.0);glEnd();//反激活纹理,防止干扰glActiveTextureARB (GL_TEXTURE0_ARB);glDisable(GL_TEXTURE_2D);glActiveTextureARB (GL_TEXTURE1_ARB);glDisable(GL_TEXTURE_2D);//同上,绘制正方形,使用号和号纹理glActiveTextureARB (GL_TEXTURE1_ARB);glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, Tname1);glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glActiveTextureARB (GL_TEXTURE2_ARB);glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, Tname2);glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBegin(GL_QUADS);glMultiTexCoord2fARB (GL_TEXTURE1_ARB,0.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE2_ARB,0.0,0.0);glVertex3f(0.5, -1.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB,0.0,1.0);glMultiTexCoord2fARB (GL_TEXTURE2_ARB,0.0,1.0);glVertex3f(0.5,1.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB, 1.0,1.0);glMultiTexCoord2fARB (GL_TEXTURE2_ARB, 1.0,1.0);glVertex3f(2.5,1.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB, 1.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE2_ARB, 1.0,0.0);glVertex3f(2.5, -1.0,0.0);glEnd();glActiveTextureARB (GL_TEXTURE1_ARB); glDisable(GL_TEXTURE_2D); glActiveTextureARB (GL_TEXTURE2_ARB); glDisable(GL_TEXTURE_2D);//绘制正方形,使用号、号和号纹理glActiveTextureARB (GL_TEXTURE0_ARB); glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, Tname0);glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glActiveTextureARB (GL_TEXTURE1_ARB);glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, Tname1);glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glActiveTextureARB (GL_TEXTURE2_ARB);glEnable(GL_TEXTURE_2D);glBindTexture(GL_TEXTURE_2D, Tname2);glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glBegin(GL_QUADS);glMultiTexCoord2fARB (GL_TEXTURE0_ARB,0.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB,0.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE2_ARB,0.0,0.0);glVertex3f(-3.5,0.0);glMultiTexCoord2fARB (GL_TEXTURE0_ARB,0.0,1.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB,0.0,1.0);glMultiTexCoord2fARB (GL_TEXTURE2_ARB,0.0,1.0);glVertex3f(-1.0, -1.5,0.0);glMultiTexCoord2fARB (GL_TEXTURE0_ARB, 1.0,1.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB, 1.0,glMultiTexCoord2fARB (GL_TEXTURE2_ARB, 1.0,1.0);glVertex3f(1.0, -1.5,0.0);glMultiTexCoord2fARB (GL_TEXTURE0_ARB, 1.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE1_ARB, 1.0,0.0);glMultiTexCoord2fARB (GL_TEXTURE2_ARB, 1.0,0.0);glVertex3f(1.0, -3.5,0.0);glActiveTextureARB (GL_TEXTURE0_ARB);}glDisable(GL_TEXTURE_2D);glActiveTextureARB (GL_TEXTURE1_ARB);glDisable(GL_TEXTURE_2D);glActiveTextureARB (GL_TEXTURE2_ARB);glDisable(GL_TEXTURE_2D);glFlush();voidreshape(intw,inth){}voidpressKey(intkey,intx,inty){}switch(key){caseGLUT_KEY_RIGHT: }X += 1;glutPostRedisplay();break;X -= 1;glutPostRedisplay();break;Y += 1;glutPostRedisplay();break;Y -= 1;glutPostRedisplay();break;glViewport(0, 0, (GLsizei) w, (GLsizei) h); glMatrixMode(GL_PROJECTION); glLoadIdentity();gluPerspective(60.0, (GLfloat) w/(GLfloat) h,1.0,30.0);glMatrixMode(GL_MODELVIEW); glLoadIdentity();gluLookAt((GLfloat)X, (GLfloat)Y, (GLfloat)Z, 0.0,0.0,0.0,0.0,1.0,0.0);//视图变换caseGLUT_KEY_LEFT: caseGLUT_KEY_UP:caseGLUT_KEY_DOWN:default:intmain(intargc,char** argv){}glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(250, 250);glutInitWindowPosition(100, 100);glutCreateWindow(argv[0]);init();glutDisplayFunc(display);glutReshapeFunc(reshape);glutSpecialFunc(pressKey);glutMainLoop();return0;【程序截图】【说明】对于Windows平台下,需要包含glext.h头文件。

OpenGL教程

OpenGL教程

在谈出的对话框左边点 Application Settings,找到 Empty project 并勾上,选择 Finish。 然后向该工程添加一个代码文件,取名为“OpenGL.c”,注意用.c 来作为文件结尾。 搞定了,就跟平时的工程没什么两样的。
=====================未完,请勿跟帖=====================
该程序的作用是在一个黑色的窗口中央画一个白色的矩形。下面对各行语句进行说明。
=====================未完,请勿跟帖=====================
怎么样?代码还不算长吧?
首先,需要包含头文件#include <GL/glut.h>,这是 GLUT 的头文件。 本来 OpenGL 程序一般还要包含<GL/gl.h>和<GL/glu.h>,但 GLUT 的头文件中已经自动将 这两个文件包含了,不必再次包含。
可以想象,通过点、直线和多边形,就可以组合成各种几何图形。甚至于,你可以把一段弧 看成是很多短的直线段相连,这些直线段足够短,以至于其长度小于一个像素的宽度。这样 一来弧和圆也可以表示出来了。通过位于不同平面的相连的小多边形,我们还可以组成一个 “曲面”。
=====================未完,请勿跟帖=====================
OpenGL 程序如下:(注意,如果需要编译并运行,需要正确安装 GLUT,安装 方法如上所述)
#include <GL/glut.h>
void myDisplay(void) {
glClear(GL_COLOR_BUFFER_BIT); glRectf(-0.5f, -0.5f, 0.5f, 0.5f); glFlush(); }

OpenGl绘制一个立方体

OpenGl绘制一个立方体

OpenGl绘制⼀个⽴⽅体OpenGl 绘制⼀个⽴⽅体 为了绘制六个正⽅形,我们为每个正⽅形指定四个顶点,最终我们需要指定6*4=24个顶点。

但是我们知道,⼀个⽴⽅体其实总共只有⼋个顶点,要指定24次,就意味着每个顶点其实重复使⽤了三次,这样可不是好的现象。

最起码,像上⾯这样重复烦琐的代码,是很容易出错的。

稍有不慎,即使相同的顶点也可能被指定成不同的顶点了。

如果我们定义⼀个数组,把⼋个顶点都放到数组⾥,然后每次指定顶点都使⽤指针,⽽不是使⽤直接的数据,这样就避免了在指定顶点时考虑⼤量的数据,于是减少了代码出错的可能性。

// 将⽴⽅体的⼋个顶点保存到⼀个数组⾥⾯ ⽴⽅体的各个顶点的顺序如下图所⽰:1. 定义⽴⽅体的各个顶点数组 将⽴⽅体的⼋个顶点保存到⼀个数组⾥⾯。

这样在指定顶点时,⽤指针,⽽不⽤直接⽤具体的数据。

1// 将⽴⽅体的⼋个顶点保存到⼀个数组⾥⾯2static const GLfloat vertex_list[][3] = {3 -0.5f, -0.5f, -0.5f,40.5f, -0.5f, -0.5f,5 -0.5f, 0.5f, -0.5f,60.5f, 0.5f, -0.5f,7 -0.5f, -0.5f, 0.5f,80.5f, -0.5f, 0.5f,9 -0.5f, 0.5f, 0.5f,100.5f, 0.5f, 0.5f,11 }; 使⽤时可以直接采⽤指针绘制。

1 glBegin(GL_QUADS);2 glVertex3fv(vertex_list[0]);3 glVertex3fv(vertex_list[2]);4 glVertex3fv(vertex_list[3]);5 glVertex3fv(vertex_list[1]);67// ...8 glEnd(); 很容易就看出第0, 2, 3, 1这四个顶点构成⼀个正⽅形。

稍稍观察就可以发现,我们使⽤了⼤量的glVertex3fv函数,其实每⼀句都只有其中的顶点序号不⼀样,因此我们可以再定义⼀个序号数组,把所有的序号也放进去。

openGL大作业五星红旗

openGL大作业五星红旗

学院目录1 摘要 (3)1.1设计题目 (3)1.2设计内容 (3)1.3开发工具 ................................................ 错误!未定义书签。

1.4应用平台 ................................................ 错误!未定义书签。

2 详细设计 ....................................................... 错误!未定义书签。

2.1程序结构 ................................................ 错误!未定义书签。

2.2主要功能 (6)2.3函数实现 (6)2.4开发日志 (6)3 程序调试及运行 (7)3.1程序运行结果......................................... 错误!未定义书签。

3.2程序使用说明 (8)3.3程序开发总结 (8)4 附件(源程序) (9)1 摘要1.1 设计题目利用Opengl的知识,绘制一面五星红旗。

1.2 设计内容编写此程序实现绘制五星红旗。

2.1函数结构1.init 函数此函数实现了窗口背景和投影参数的初始设置void init (void){glClearColor(1.0,1.0,1.0,1.0); //窗口背景设置为白色glMatrixMode(GL_PROJECTION); //设置投影参数gluOrtho2D(0.0,200.0,0.0,150.0);}2.TRIANGLE 函数此函数实现了图形中各个关键点的坐标输入,使图像有基本框架void TRIANGLE(float i,float j,int r){ float PI = 3.14;f loat ax,ay,bx,by,cx,cy,dx,dy,ex,ey;ax=0;ay=r;bx=r*cos(18*PI/180);by=r*sin(18*PI/180);ex=-bx;ey=by;cx=r*sin(36*PI/180);cy=-r*cos(36*PI/180);dx=-cx;dy=cy;glColor3f(1.0,1.0,0.0);glBegin(GL_TRIANGLES);glVertex2i(i,j);glVertex2i(i+ax,j+ay);glVertex2i(i+dx,j+dy);glEnd();glBegin(GL_TRIANGLES);glVertex2i(i,j);glVertex2i(i+ax,j+ay);glVertex2i(i+cx,j+cy);glEnd();glBegin(GL_TRIANGLES);glVertex2i(i,j);glVertex2i(i+bx,j+by);glVertex2i(i+ex,j+ey);glEnd();glBegin(GL_TRIANGLES);glVertex2i(i,j);glVertex2i(i+bx,j+by);glVertex2i(i+dx,j+dy);glEnd();glBegin(GL_TRIANGLES);glVertex2i(i,j);glVertex2i(i+cx,j+cy);glVertex2i(i+ex,j+ey);glEnd();}3. flagSegment 函数此函数实现了对图形颜色的渲染,函数如下:void flagSegment(void){ glMatrixMode(GL_MODELVIEW);glLoadIdentity();glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glColor3f(1.0,0.0,0.0); //颜色为红色glBegin(GL_QUADS);glVertex2i(13,140);glVertex2i(100,140);glVertex2i(100,80);glVertex2i(13,80);glEnd();TRIANGLE(28,123,9);glTranslatef(40.0f,135.0f,0.0f);glPushMatrix();glRotatef(-30.0f,0.0f,0.0f,1.0f);TRIANGLE(0,0,4);glPopMatrix();glTranslatef(7.0f,-7.0f,0.0f);glPushMatrix();glRotatef(30.0f,0.0f,0.0f,1.0f);TRIANGLE(0,0,4);glPopMatrix();glTranslatef(0.0f,-10.0f,0.0f);TRIANGLE(0,0,4);glTranslatef(-7.0f,-6.0f,0.0f);glPushMatrix();glRotatef(-30.0f,0.0f,0.0f,1.0f);TRIANGLE(0,0,4);glPopMatrix();glFlush(); //渲染}4.main函数这个函数是此程序的主函数, glutInit完成初始化GLUT,glutInitDisplayMode完成显示模式设置,glut InitDisplayMode完成左上角位置设置,glut IntWindowSize 完成窗口的长和高。

Opengl绘制我们的小屋(一)球体,立方体绘制

Opengl绘制我们的小屋(一)球体,立方体绘制

Opengl绘制我们的⼩屋(⼀)球体,⽴⽅体绘制这个系列我想⽤来运⽤opengl红⽪书的前⼋章节的内容,来打造⼀个室内⼩屋.这⼀章主要是定义⼏个基本的结构.并给出球体与⽴⽅体的画法,先让我们来定义⼀些基本的结构.⼀个是包含点,法向量,纹理贴图向量,⼆是矩形与圆形的⽗类,包含⼀些基本公有的处理. 1type T2N3V3 =2struct3val mutable TexCoord : Vector24val mutable Normal : Vector35val mutable Position : Vector36new(v,n,p) = {TexCoord = v;Normal = n;Position = p}7end8 [<AbstractClass>]9type Shape() =10let mutable bCreate = false11let mutable vi = 012let mutable ei = 013let mutable count = 014member this.vboID with get() = vi and set value = vi <- value15member this.eboID with get() = ei and set value = ei <- value16member this.TriangelCount with get() = count and set value = count <- value17member this.IsCreate with get() = bCreate and set value = bCreate <- value18abstract Draw : unit -> unit19abstract Init : unit -> unit20member this.InitQ : unit -> unit =fun () -> ()View Code然后是球体的画法,相关具体过程如上篇,先贴上代码,我会对其中⼀些做些说明.1type Sphere(radius:float32,level:int) =2inherit Shape()3let mutable rad,lev = radius,level4let RightLevel =5if lev < 0then lev <- 06 elif lev > 6then lev <-67override this.Draw() =8if this.IsCreate<>true then this.Init()9 GL.BindBuffer(BufferTarget.ArrayBuffer,this.vboID)10 GL.BindBuffer(BufferTarget.ElementArrayBuffer,this.eboID)11 GL.InterleavedArrays(InterleavedArrayFormat.T2fN3fV3f,0,IntPtr.Zero)12 GL.DrawElements(BeginMode.Triangles,this.TriangelCount,DrawElementsType.UnsignedInt,IntPtr.Zero)13override this.Init() =14let alls = Array.create 6 (new T2N3V3())15 alls.[0] <- new T2N3V3(new Vector2( 0.0f, 0.0f ), Vector3.UnitX, Vector3.UnitX * rad )16 alls.[1] <- new T2N3V3(new Vector2( 0.0f, 0.0f ), Vector3.UnitY, Vector3.UnitY * rad )17 alls.[2] <- new T2N3V3(new Vector2( 0.0f, 0.0f ), Vector3.UnitZ, Vector3.UnitZ * rad )18 alls.[3] <- new T2N3V3(new Vector2( 0.0f, 0.0f ), -Vector3.UnitX, -Vector3.UnitX * rad )19 alls.[4] <- new T2N3V3(new Vector2( 0.0f, 0.0f ), -Vector3.UnitY, -Vector3.UnitY * rad )20 alls.[5] <- new T2N3V3(new Vector2( 0.0f, 0.0f ), -Vector3.UnitZ, -Vector3.UnitZ * rad )21let is = [|221;2;0230;2;4240;4;5255;1;0261;3;2274;2;3284;3;5291;5;330 |]31let (vvv:T2N3V3 []),(iv: int[]) = this.Sub (alls,is)32let mutable vID,eID = 0,033//let mutable tv,vv,pv = vvv |> Array.map (fun v -> v.TexCoord,v.Normal,v.Position) |> Array.unzip334 GL.GenBuffers(1,&vID)35 GL.BindBuffer(BufferTarget.ArrayBuffer,vID)36 GL.BufferData(BufferTarget.ArrayBuffer,IntPtr (4 * 8 * vvv.Length),vvv,BufferUsageHint.StaticDraw)3738 GL.GenBuffers(1,&eID)39 GL.BindBuffer(BufferTarget.ElementArrayBuffer,eID)40 GL.BufferData(BufferTarget.ElementArrayBuffer,IntPtr (4 * iv.Length),iv,BufferUsageHint.StaticDraw)4142 this.vboID <- vID43 this.eboID <- eID44 this.TriangelCount <- iv.Length45 this.IsCreate <- true46 ()47member v.GetMidValue (first:T2N3V3,second:T2N3V3) =48let midN = Vector3.Lerp(first.Position,second.Position,0.5f) |> Vector3.Normalize49let midP = midN *(float32 rad)50let midT = Vector2.Lerp(first.TexCoord,second.TexCoord,0.5f) |> Vector2.Normalize51let result = new T2N3V3(midT,midN,midP)52 result53member v.Subdivide (v1:T2N3V3,v2:T2N3V3,v3:T2N3V3) =54let vs = Array.create 6 (new T2N3V3())55 vs.[0] <- v156 vs.[1] <- v.GetMidValue(v1,v2)57 vs.[2] <- v.GetMidValue(v3,v1)58 vs.[3] <- v259 vs.[4] <- v.GetMidValue(v2,v3)60 vs.[5] <- v361let is = Array.create 12062 is.[0] <- 063 is.[1] <- 164 is.[2] <- 265 is.[3] <- 266 is.[4] <- 167 is.[5] <- 468 is.[6] <- 469 is.[7] <- 170 is.[8] <- 371 is.[9] <- 272 is.[10] <-473 is.[11] <- 574 (vs,is)75member this.Sub(alls:T2N3V3 [],is:int []) =76//let mutable tv,vv,pv = alls |> Array.map (fun v -> v.TexCoord,v.Normal,v.Position) |> Array.unzip377let mutable allv = alls78let mutable iv = is79let show array = printfn "%A" array80for j in0 .. lev do81let mutable av = Array.create 0 (new T2N3V3())82let mutable ev = Array.create 0083 printfn "%i" allv.Length84 printfn "%i" iv.Length85for i in0 .. 3 .. iv.Length - 1do86let (vvv,iiv) = this.Subdivide(allv.[iv.[i]],allv.[iv.[i+1]],allv.[iv.[i+2]])87let length = av.Length88 av <- Array.append av vvv89let map = iiv |> Array.map (fun p -> p + length)90 ev <- Array.append ev map91 allv <- av92 iv <- ev93 allv |> Array.map (fun p -> p.Position) |> show94 show iv95 allv,ivView Code初始化需要的⼆个参数,分别代表球的⼤⼩(radius),与画的细分程度(level).其中相关如何绘制球体代码在上⽂有讲,相当于有是把⼀个分别位于x,y,z各(+radius,-radius)这六个点,组成的⼀个⼋个三⾓形,索引点的位置如Init⾥GL.InterleavedArrays(InterleavedArrayFormat.T2fN3fV3f,0,IntPtr.Zero)其中的T2fN3fV3f对应于我们的数据结构T2N3V3,这个函数分别相当于指定GL.TexCoordPointer,GL.NormalPointer,GL.VertexPointer(还会打开相应状态),会⾃动给我们处理好,我们也可以只指定顶点,如下GL.VertexPointer(3,VertexPointerType.Float,4*8,IntPtr (4*8-4*5)),这些数据之间的间隔对应与我们前⾯写⼊的GL.BufferData(BufferTarget.ArrayBuffer,IntPtr (4 * 8 * vvv.Length),vvv,BufferUsageHint.StaticDraw)其中vvv是T2N3V3的结构.基本的GL.BindBuffer的对应的三个处理就不细说了,在Draw⾥,BindBuffer是指定我们当前格式数据在存储位置,然后分别调⽤InterleavedArrays设定各顶点的状态,然后是调⽤DrawElements对应上⾯的GL.BindBuffer(BufferTarget.ElementArrayBuffer,this.eboID)处理.然后是⽴⽅体的绘制,其中⽴⽅体的绘制⽤的⽅法看起来会容易理解.如下1type Cube(width:float32,height:float32,length:float32,index:int) =2inherit Shape()3let mutable id = index4let xl,yl,zl =width/2.f,height/2.f,length/2.f5let mutable color = Color.White6let v8 = [|7new Vector3(xl,yl,zl)8new Vector3(-xl,yl,zl)9new Vector3(-xl,-yl,zl)10new Vector3(xl,-yl,zl)11new Vector3(xl,yl,-zl)12new Vector3(-xl,yl,-zl)13new Vector3(-xl,-yl,-zl)14new Vector3(xl,-yl,-zl)15 |]16new(x,y,z) =17let rnd = System.Random().Next()18 printfn "%i" rnd19 Cube(x,y,z,-1)20override this.Draw() =21if this.IsCreate<>true then this.Init()22 GL.EnableClientState(ArrayCap.VertexArray)23 GL.EnableClientState(ArrayCap.NormalArray)24 GL.BindBuffer(BufferTarget.ArrayBuffer,this.vboID)25 GL.VertexPointer(3,VertexPointerType.Float,0,IntPtr.Zero)26 GL.PushMatrix()27if id >= 0 && id < 8then28 GL.Translate(v8.[id])29 GL.Color3(this.Color:Color)30 GL.Normal3(Vector3.UnitZ)31 GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,[|0;1;2;0;2;3|])32//GL.Color3(Color.Black)33 GL.Normal3(Vector3.UnitY)34 GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,[|4;5;1;4;1;0|])35//GL.Color3(Color.Red)36 GL.Normal3(Vector3.UnitX)37 GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,[|4;0;3;4;3;7|])38//GL.Color3(Color.Green)39 GL.Normal3(-Vector3.UnitY)40 GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,[|3;2;6;3;6;7|])41//GL.Color3(Color.Blue)42 GL.Normal3(-Vector3.UnitX)43 GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,[|1;5;6;1;6;2|])44//GL.Color3(Color.DodgerBlue)45 GL.Normal3(-Vector3.UnitZ)46 GL.DrawElements(BeginMode.Triangles,6,DrawElementsType.UnsignedInt,[|5;4;7;5;7;6|])47 GL.PopMatrix()48override this.Init() =49let mutable vID = 050 GL.GenBuffers(1,&vID)51 GL.BindBuffer(BufferTarget.ArrayBuffer,vID)52 GL.BufferData(BufferTarget.ArrayBuffer,IntPtr (4 * 3 * v8.Length),v8,BufferUsageHint.StaticDraw)53 this.vboID <- vID54 this.IsCreate <- true55let rnd = System.Random(this.GetHashCode())56 this.Color <- Color.FromArgb(rnd.Next(0,255),rnd.Next(0,255),rnd.Next(0,255))57 ()58member this.Index with get() = id and set value = id <-value59member this.Color with get() = color and set value = color <- valueView Code上图中的V8分别对应其中的0-7个顶点,GL.DrawElements后⾯的0;1;2;0;2;3分别是以三⾓形的画法来画⼀个正⽅形.⽴⽅体的画法主要是确定宽,⾼,长,我们这样定义,我们站在原点上,⾯向Z+轴,我们的⼿展开来表⽰X轴(对应宽度),⽽我们的⾝⾼表⽰Y轴(对应⾼度),和我们⾯向距离的长远来表⽰Z轴,(对应长度).绘制也是8个⾯,和上⾯⼀样,也是在缓存中记录顶点,但是不⼀样的是,顶点索引是在绘制时没有⽤到顶点索引缓存,主要考虑后⾯有法向量的处理,还有现在没有加上的纹理贴图的处理.在这⾥,我们要特别注意,顶点顺序问题,在opengl,默认正⾯是逆时针,⽽我们可以看0;1;2;0;2;3对应图上的顺序.然后⼤家可能会发现,画⽴⽅体的后⾯5;4;7;5;7;6,这个顺序好像不对,是顺时针的.⼤家可以想象下,我们在门外看门的逆时针画法与我们在门内看门外顺时针的画法是⼀样的.所以如果我们要画后⾯4,5,6,7我们以为的是逆时针是不对的,我们要想象我们在那边来看,然后再画,应该是5,4,7,6这个⽅向.其中纹理贴图后⾯会说,和这处理也有类似.在上⾯,我们看到我们都没对顶点的颜⾊来定义,这⾥没必要,因为后⾯我们肯定要⽤到灯光,⽤到灯光的话,设置的颜⾊都没⽤,我们会⽤到灯光颜⾊与材质的颜⾊.纹理贴图也有没对应处理,这⾥在后⾯我会根据讲到再来改写相关处理.下⼀节,主要是讲第⼀⼈称漫游的相关处理.。

一个简单的OpenGL拾取例子

一个简单的OpenGL拾取例子

一个简单的OpenGL拾取例子【注】OpenGL鼠标拾取的大致样子。

唉,一个堂堂的“医生”,竟然要做这些coding的体力活。

真丢人啊!!#include <GL/glut.h>#include <stdlib.h>#include <stdio.h>void init(){glClearColor(0, 0, 0, 0);}void drawObjects(GLenum mode){if (mode == GL_SELECT) glLoadName(1);glColor3f(1, 0, 0);glRectf(-0.5, -0.5, 1.0, 1.0);if (mode == GL_SELECT) glLoadName(2);glColor3f(0, 0, 1);glRectf(-1.0, -1.0, 0.5, 0.5);}void display(){glClear(GL_COLOR_BUFFER_BIT);drawObjects(GL_RENDER);glFlush();}void processHits(GLint hits, GLuint buffer[]){unsigned int i, j;GLuint names, *ptr;ptr = (GLuint*)buffer;for (i=0; i<hits; i++) {names = *ptr;ptr += 3; // 跳过名字数和深度for (j=0; j<names; j++) {if (*ptr == 1)printf("red\n");elseprintf("blue\n");ptr++;}}#define SIZE 512#define N 5void mouse(int button, int state, int x, int y){GLuint selectBuf[SIZE];GLint hits;GLint viewport[4];if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {glGetIntegerv(GL_VIEWPORT, viewport);// 初始化名称堆栈glSelectBuffer(SIZE, selectBuf);glRenderMode(GL_SELECT);glInitNames();glPushName(0);glMatrixMode(GL_PROJECTION);glPushMatrix();glLoadIdentity();// 定义一个以光标为中心的NxN拾取区域// 必须对鼠标y坐标求反,从屏幕坐标系转换成世界坐标系gluPickMatrix(x, viewport[3]-y, N, N, viewport);gluOrtho2D(-2, 2, -2, 2);drawObjects(GL_SELECT);glMatrixMode(GL_PROJECTION);glPopMatrix();glFlush();hits = glRenderMode(GL_RENDER);processHits(hits, selectBuf);glutPostRedisplay();}}void reshape(int w, int h)glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION); glLoadIdentity();gluOrtho2D(-2, 2, -2, 2);glMatrixMode(GL_MODELVIEW); glLoadIdentity();}void keyboard(unsigned char key, int x, int y){switch(key){case 'q':exit(0);break;}}int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(500, 500); glutInitWindowPosition(100, 100); glutCreateWindow("123");init();glutReshapeFunc(reshape);glutDisplayFunc(display);glutMouseFunc(mouse);glutKeyboardFunc(keyboard);glutMainLoop();return 0;}。

OpenGL进行简单的通用计算实例

OpenGL进行简单的通用计算实例

OpenGL进⾏简单的通⽤计算实例博主作为OpenGL新⼿,最近要⽤OpenGL进⾏并⾏的数据计算,突然发现这样的资料还是很少的,⼤部分资料和参考书都是讲⽤OpenGL进⾏渲染的。

好不容易找到⼀本书《GPGPU编程技术,从OpenGL、CUDA到OpenCL》,⾥⾯对并⾏处理的发展进⾏了系统性的介绍,还是很不错的。

⼩⽩博主很兴奋,看完书中第三章后恍然⼤悟了很多,就贴出书中代码3-3的例⼦,实现⼀番,并⽤⼀副图⽚数据做了实现。

实现环境:Window7 32bit, VS2013+OpenGL3.3+GLEW+GLFW。

OpenGL⽤来进⾏通⽤数据计算的流程如下图,数据从CPU(应⽤程序)中通过“⽤绘制来调⽤”发送到纹理缓存,以纹理映射的⽅式给到着⾊器,最后经过⽚段着⾊器的计算(GLSL语⾔)后,再将结果输出到纹理缓存,最后CPU(应⽤程序)再从纹理缓存中读取结果数据,⾄此计算完成。

1.书中代码3-3,输⼊⼀组数据到纹理缓存,然后再从纹理缓存中读取这组数据,代码以及实验结果如下:数据类型就设置为float,将数据发送⾄纹理缓存要⽤这个函数glTexSubImage2D( );#include <iostream>#include <stdlib.h>#include <stdio.h>#define GLEW_STATIC#include <GL/glew.h>#include <GLFW/glfw3.h>using namespace std;#define WIDTH 2#define HEIGHT 3int main(int argc, char** argv){int nWidth=(int)WIDTH;int nHeight=(int)HEIGHT;int nSize=(int)nWidth*nHeight;//创建输⼊数据float* pfInput=new float[4*nSize];float* pfOutput=new float[4*nSize];for (int i=0; i<nSize*4; i++){pfInput[i]= (float)(i + 1.2345);}//初始化并设置GLFWglfwInit();glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);//创建GLFW窗⼝GLFWwindow* window = glfwCreateWindow(3, 2, "LearnOpenGL", nullptr, nullptr);glfwMakeContextCurrent(window);//初始化GLEW//glewExperimental = GL_TRUE;glewInit();//创建FBO并绑定GLuint fb;glGenFramebuffersEXT(1, &fb);glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb);//创建纹理对象并绑定GLuint tex;glGenTextures(1, &tex);glBindTexture(GL_TEXTURE_2D, tex);//设置纹理参数glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);//将纹理关联到FBOglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex, 0); //将纹理数据设置为单精度浮点数glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA_FLOAT32_ATI, nWidth, nHeight,0, GL_RGBA, GL_FLOAT, NULL);//将数据传⾄输⼊纹理缓存//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, nWidth, nHeight, 0, GL_RGBA, GL_FLOAT, pfInput);glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, nWidth, nHeight, GL_RGBA, GL_FLOAT, pfInput);//从输出纹理缓存中读出数据glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);glReadPixels(0,0, nWidth, nHeight, GL_RGBA, GL_FLOAT, pfOutput);//打印并检查结果bool bCap=true;for (int i=0; i<nSize*4; i++){cout<<i<<":\t"<<pfInput[i]<<'\t'<<pfOutput[i]<<endl;if (pfInput[i]!=pfOutput[i]) bCap=false;}if (bCap) cout<<"Round trip complete!"<<endl;else cout<<"Round trip failed!" <<endl;delete pfInput;delete pfOutput;glDeleteFramebuffers(1, &fb);glDeleteTextures(1, &tex);system("pause");return0;}View Code2.读取⼀幅图像,写⼊纹理缓存并从纹理缓存读出,配合OpenCV使⽤。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

先编译运行一个简单的例子,这样我们可以有一个直观的印象。

从这个例子我们可以看到OpenGL可以做什么,当然这个例子只做了很简单的一件事--绘制一个彩色的三角形。

除此以外,我们还可以看到典型的OpenGL程序结构及openGL的运行顺序。

例1:本例在黑色的背景下绘制一个彩色的三角形,如图一所示。

图一:一个彩色的三角形首先创建工程,其步骤如下:
1)创建一个Win32 Console Application。

2)链接OpenGL libraries。

在Visual C++中先单击Project,再单击Settings,再找到Link单击,最后在Object/library modules 的最前面加上OpenGL32.lib GLu32.lib GLaux.lib
3)单击Project Settings中的C/C++标签,将Preprocessor definitions 中的_CONSOLE改为__WINDOWS。

最后单击OK。

现在你可以把下面的例子拷贝到工程中去,编译运行。

你可以看到一个彩色的三角形。

我们先看看main函数。

函数中以glut开头的函数都包含在glut.h中。

GLUT库的函数主要执行如处理多窗口绘制、处理回调驱动事件、生成层叠式弹出菜单、绘制位图字体和笔画字体,以及各种窗口管理等任务。

·glutInit用来初始化GLUT库并同窗口系统对话协商。

·glutInitDisplayMode用来确定所创建窗口的显示模式。

本例中的参数GLUT_SINGLE 指定单缓存窗口,这也是缺省模式,对应的模式为GLUT_DOUBLE 双缓存窗口。

参数GLUT_RGB指定颜色RGBA模式,这也是缺省模式,对应的模式为GLUT_INDEX 颜色索引模式窗口。

·glutInitWindowSize初始化窗口的大小,第一个参数为窗口的宽度,第二个参数为窗口的高度,以像素为单位。

·glutInitWindowPosition设置初始窗口的位置,第一个参数为窗口左上角x的坐标,第二个参数为窗口左上角y的坐标,以像素为单位。

屏幕的左上角的坐标为(0,0),横坐标向右逐渐增加,纵坐标向下逐渐增加。

·glutCreateWindow创建顶层窗口,窗口的名字为扩号中的参数。

·background() 这是自己写的函数,设置背景。

其实这个函数中的语句可以写在display 函数中,但为了使功能块更加清晰,所以把背景这一部分单独提出来。

·glutReshapeFunc注册当前窗口的形状变化回调函数。

当改变窗口大小时,该窗口的形状改变回调函数将被调用。

在此例中就是myReshape指定形状变化函数。

·glutDisplayFunc注册当前窗口的显示回调函数。

当一个窗口的图像层需要重新绘制时,GLUT将调用该窗口的的显示回调函数。

在此例中的mydisplay就是显示回调函数,显示回调函数不带任何参数,它负责整个图像层的绘制。

我们的大部分工作将集中在这个函数中。

·glutMainLoop进入GLUT事件处理循环。

glutMainLoop函数在GLUT程序中最多只能调用一次,它一旦被调用就不再返回,并且调用注册过的回调函数。

所以这个函数必须放在注册回调函数的后面,此例中为glutReshapeFunc,glutDisplayFunc。

现在我们对OpenGL程序的典型的程序结构有了一个了解。

首先初始化,包括对GLUT 库的初始化和对窗口的设置及显示模式的设置。

第二,创建窗口。

第三,自己创作的核心部分。

第四,glutMainLoop进入GLUT事件处理循环。

下面,我们转到我们的创作核心。

background这个函数很简单,只有一行语句。

glClearColor中的四个参数分别是红、绿、蓝和alpha值。

这些值定义了窗口的颜色。

这些值的范围在[0,1]之间。

缺省值均为0。

你可以改变这些值,观察背景色彩的变化。

myDisplay画了一个彩色的三角形。

·glClear将buffers设置为预先设定的值。

参数GL_COLOR_BUFFER_BIT表明现在可以向buffer中写入颜色值。

·glBegin和glEnd是一一对应的。

这两个函数限制了一组或多组图元的顶点定义。

在这两个函数中间就是你所绘制的由多个顶点组成的图元。

函数的参数表明了所绘制的图元的类型。

本例中的GL_TRIANGLES 表明所绘制的图形为三角形。

·glShadeModel选择平坦或光滑渐变模式。

GL_SMOOTH为缺省值,为光滑渐变模式,GL_FLAT为平坦渐变模式。

·glColor设置当前颜色。

后面跟的数字为参数个数。

3表明有三个参数,分别为红、绿、蓝,4则多一个参数alpha。

紧跟数字后面的字母表示数据类型。

本例中的glColor3f表示三个参数,数据类型为GLfloat。

·glVertex指定顶点。

同样函数明中的数字表明参数个数。

参数分别为x,y或x、y、z。

紧跟数字后面的字母表示数据类型。

本例中glVertex2f表明两个参数,数据类型为GLfloat。

窗口的中心为原心,坐标为(0,0,0)。

横坐标向左为负,向右为正;纵坐标向上为正,向下为负;z坐标向屏幕里为负,屏幕外为正,坐标系符合右手定则。

现在你将main函数中的glutReshapeFunc(myReshape); 注释掉,任意改变三角形顶点的坐标你会发现窗口的最左边,最右边的x值分别为-1和1,而窗口的最上端,最下端的y值分别为1和-1。

由此可见glVertex中坐标的值实际上是和窗口的大小成倍数的关系。

好了,现在恢复原来的程序。

·glFlush迫使OpenGL函数在有限时间里运行。

glFlush清空所有buffer,使所有发出的命令能在规定的时间内运行。

一定不能忘记这一条语句。

只有加了这一句,前面的命令才能执行。

myReshape改变窗口的大小。

·glViewport(Glint x,Glint y,GLsizei width,GLsizei height)设置视口。

视口是一个矩形,x,y为视口左下角的坐标,以像素为单位,缺省值为(0,0)。

width和height分别
为视口的宽和高。

OpenGl context第一次贴到窗口上时width和height分别设置成窗口的大小。

·glMatrixMode指明哪一个矩阵为当前矩阵。

本例中GL_PROJECTION指明投影矩阵堆栈为随后的矩阵操作的目标。

GL_MODELVIEW指明模型视景矩阵。

·glLoadIdentity将当前矩阵置换为单位阵。

·gluOrtho2D(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top)定义二维正视投影矩阵。

left,right分别设置左右垂直切平面的坐标,bottom,top分别设置上下垂直切平面的坐标。

现在你可能对这几个参数的意义还不是很清楚。

我们现在将myReshape函数glLoadIdentity();后面所有的语句注释掉。

加上gluOrtho2D(-1.5,1.5,-1.5,1.5);改变三角型的坐标及gluOrtho2D中的数值,你就可以清楚的理解gluOrtho2D中数值的含义。

现在,你应该大致了解OpenGL到底是怎么一回事。

通过这一节的学习我们知道怎样使用颜色及绘制几何图形及物体的最基本的函数,更多的函数你可以在网上或有关书中查到。

下一节我们继续讲一下颜色的使用。

相关文档
最新文档