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使⽤。

OpenGL一个简单的例子

OpenGL一个简单的例子

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

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

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

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

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

2)链接OpenGL libraries。

在Visual C++中先单击Project,再单击Settings,再找到Link单击,最后在Object/library modules 的最前面加上OpenGL32.lib GLu32.lib GLaux.lib3)单击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的坐标,以像素为单位。

opengl 立方体 纹理 顶点 索引 定义 -回复

opengl 立方体 纹理 顶点 索引 定义 -回复

opengl 立方体纹理顶点索引定义-回复OpenGL立方体纹理顶点索引定义OpenGL是一种图形编程接口,用于渲染2D和3D图形。

在OpenGL中,我们可以使用纹理贴图来给图形对象添加更多的细节和逼真感。

本文将重点讨论如何使用顶点和索引来定义一个带有纹理的立方体。

第一步:顶点定义在OpenGL中,一个3D对象的顶点通常使用(x, y, z)坐标来表示。

对于立方体而言,我们可以使用8个顶点来定义。

一个立方体的八个顶点可以如下定义:顶点1: (-1.0, 1.0, 1.0)顶点2: (1.0, 1.0, 1.0)顶点3: (-1.0, -1.0, 1.0)顶点4: (1.0, -1.0, 1.0)顶点5: (-1.0, 1.0, -1.0)顶点6: (1.0, 1.0, -1.0)顶点7: (-1.0, -1.0, -1.0)顶点8: (1.0, -1.0, -1.0)这些坐标定义了立方体的8个顶点,每个顶点都具有一个唯一的坐标。

第二步:纹理坐标定义在OpenGL中,我们可以为每个顶点定义一个纹理坐标。

纹理坐标用来确定在纹理贴图中的哪个位置采样颜色。

纹理坐标通常使用(u, v)坐标表示,并且取值范围从0到1。

对于立方体来说,我们可以为每个顶点定义一个纹理坐标。

纹理坐标可以如下定义:顶点1: (0.0, 1.0)顶点2: (1.0, 1.0)顶点3: (0.0, 0.0)顶点4: (1.0, 0.0)顶点5: (0.0, 1.0)顶点6: (1.0, 1.0)顶点7: (0.0, 0.0)顶点8: (1.0, 0.0)这些纹理坐标定义了立方体的每个顶点在纹理贴图中的采样位置。

第三步:索引定义在OpenGL中,我们通常使用索引数组来确定如何连接顶点以形成图形对象。

对于立方体而言,我们可以使用索引来确定每个顶点的连接关系。

编写一个索引数组可以减少顶点的重复定义,从而节省内存。

立方体的索引定义如下所示:索引1: 0索引2: 1索引3: 2索引4: 3索引5: 4索引6: 5索引7: 6索引8: 7索引9: 0索引10: 4索引11: 1索引12: 5索引13: 2索引14: 6索引15: 3索引16: 7索引17: 0索引18: 2索引19: 1索引20: 3索引21: 4索引22: 6索引23: 5索引24: 7这些索引定义了顶点之间的连接关系,从而构建了立方体的形状。

一个简单的案例_OpenGL ES 3.x游戏开发(下卷)_[共3页]

一个简单的案例_OpenGL ES 3.x游戏开发(下卷)_[共3页]

第4章真实光学环境的模拟116提示上述距离、坐标位置都是以对应到屏幕的近平面坐标系计算的,即屏幕的中心点为原点,x轴正向向右,y轴正向向上,屏幕的宽度为2倍的ratio(屏幕的宽高比),高度为2。

了解了镜头光晕的基本原理后,下面简单介绍本节案例的开发思路。

本节案例中进行了两轮绘制,具体内容如下。

❑第一轮采用了一个3D透视投影的摄像机对3D场景进行渲染,再根据该摄像机相关的摄像机矩阵及投影矩阵,求出光源在屏幕上的位置坐标并更新所有光晕元素的绘制位置和绘制尺寸。

❑第二轮设置了一个平行投影的摄像机,且该摄像机近平面的尺寸与第一轮设置的近平面一致,在该摄像机下对沿着从光源屏幕位置到屏幕中心位置的直线进行镜头光晕各个元素的渲染。

4.7.2 一个简单的案例了解了镜头光晕的基本实现原理后,就可以进行具体案例的开发了。

开发之前有必要先了解本节案例Sample4_8的运行效果,如图4-29所示。

▲图4-29 案例Sample4_8的运行效果说明从图4-29中可以看出,场景中的镜头光晕是由一系列光晕元素组成,不同元素带有各自的特性(颜色、位置、尺寸),并且连成一条色彩斑斓的直线。

当手指在手机屏幕上滑动时,摄像机会随之移动,镜头光晕也会相应变化,甚至消失(当光源投影位置不在可视屏幕范围内时)。

同时由于本书插图采用灰度印刷,因此可能看不清楚,读者可用真机运行本案例并进行观察。

了解了本节案例的运行效果后,下面就可以进行具体的开发了。

由于本节案例与前面很多案例的大部分代码相同,因此,这里仅仅介绍本节案例中具有代表性的代码,主要包括光晕元素类SingleFlare、光晕类Flare、界面显示类MySurfaceView以及光晕片元着色器等,具体内容如下。

(1)首先介绍光晕元素类SingleFlare,该类对象将在光晕类Flare中被创建。

在该类中主要是定义光晕元素的各个属性,并进行相应的初始化。

运行时每个SingleFlare类对象代表一种光晕元素,本案例中共创建了13种光晕元素,其具体代码如下。

一个简单的案例_OpenGL ES 3.x游戏开发(上卷)_[共4页]

一个简单的案例_OpenGL ES 3.x游戏开发(上卷)_[共4页]

7.1 初识纹理映射提示请读者特别注意的是,在本书采用的 OpenGL ES 3.0 坐标系统中,纹理坐标的原 点是纹理图的左上角,但也有一些 3D 系统采用的是以纹理图左下角为原点、S 轴向 右、T 轴向上的纹理坐标系统。

当把这种与本书不同的纹理坐标系统中的纹理坐标数 据应用到本书的案例上时,对 T 轴的坐标要做变换,否则可能会显示不正常。

变换 的方法很简单,采用“T 本书=1.0-T 左下角为原点”的公式即可。

从上述两点可以看出,纹理映射的基本思想就是,首先为图元中的每个顶点指定恰当的纹理 坐标,然后通过纹理坐标在纹理图中可以确定选中的纹理区域,最后将选中纹理区域中的内容根 据纹理坐标映射到指定的图元上。

回忆一下第 3 章介绍过的渲染管线,最终用户看到的是显示在屏幕上的像素,而像素是由片 元产生的。

因此,进行纹理映射的过程实际上就是为右侧三角形图元中的每个片元着色,用于着 色的颜色需要从左侧的纹理图中提取,具体过程如下。

首先图元中的每个顶点都需要在顶点着色器中通过 out 变量将纹理坐标传入片元着色器。

经过顶点着色器后渲染管线的固定功能部分会根据情况进行插值计算,产生对应到每个片 元的用于记录纹理坐标的 out 变量值。

最后每个片元在片元着色器中根据其接收到的记录纹理坐标的 in 变量值到纹理图中提取 出对应位置的颜色即可,提取颜色的过程一般称为纹理采样。

提示实际开发中,建议读者采用宽和高(以像素为单位)都为 2 的 n 次方的纹理图,这 在一般情况下有助于提高处理效率。

同时也需要知道,从 OpenGL ES 3.0 标准开始, 已经允许使用宽与高为非 2 的 n 次方的纹理图,这在之前的版本中并不是所有硬件 都支持的。

7.1.2 一个简单的案例介绍了纹理映射的基本原理后,本小节将给出一个将砖墙纹理映射到 3D 空间中三角形的案 例。

本案例中采用的原始纹理如图 7-2 所示,案例的具体运行效果如图 7-3 所示。

OpenGL创建一个三角形,并且颜色渐变(绿—黑—绿)

OpenGL创建一个三角形,并且颜色渐变(绿—黑—绿)

OpenGL创建⼀个三⾓形,并且颜⾊渐变(绿—⿊—绿)学习⾃:1 #include <glad/glad.h>2 #include <GLFW/glfw3.h>34 #include <iostream>5 #include <cmath>67void framebuffer_size_callback(GLFWwindow* window, int width, int height);8void processInput(GLFWwindow *window);910// 设置窗体的宽度和⾼度11const unsigned int SCR_WIDTH = 800;12const unsigned int SCR_HEIGHT = 600;1314const char *vertexShaderSource = "#version 330 core\n"15"layout (location = 0) in vec3 aPos;\n"16"void main()\n"17"{\n"18" gl_Position = vec4(aPos, 1.0);\n"19"}\0";2021const char *fragmentShaderSource = "#version 330 core\n"22"out vec4 FragColor;\n"23"uniform vec4 ourColor;\n"24"void main()\n"25"{\n"26" FragColor = ourColor;\n"27"}\n\0";2829int main()30 {31// 初始化glfw32 glfwInit();33 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);34 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);35 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);3637// 条件编译语句,如果是苹果系统?38 #ifdef __APPLE__39 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // uncomment this statement to fix compilation on OS X40#endif4142// 创建glfw窗体43 GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);44if (window == NULL)45 {46 std::cout << "Failed to create GLFW window" << std::endl;47 glfwTerminate();48return -1;49 }50 glfwMakeContextCurrent(window);51 glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);5253// glad: load all OpenGL function pointers54// ---------------------------------------55if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))56 {57 std::cout << "Failed to initialize GLAD" << std::endl;58return -1;59 }6061// 创建并编译着⾊器62// vertex shader63int vertexShader = glCreateShader(GL_VERTEX_SHADER);64//glShaderSource函数把要编译的着⾊器对象作为第⼀个参数。

一个OPENGL台球实例

一个OPENGL台球实例

//一个OPENGL台球实例――――#include <gl/glut.h>#include <stdio.h>#include <stdlib.h>#include <math.h>#include <string.h>#include <time.h>#include <windows.h>#include <mmsystem.h>#pragma comment(lib, "OPENGL32.LIB")#pragma comment(lib, "glu32.lib")#pragma comment(lib, "glaux.lib")#pragma comment(lib, "winmm.lib")#define WIDTH 1024#define HEIGHT 768#define BMP_Header_Length 54#define PI 3.1415926#define L0 GL_LIGHT0#define L1 GL_LIGHT1//变量申明GLint font=(int)GLUT_BITMAP_HELVETICA_12,width=1024,height=768; GLuint texGround,texWall,thb,texzb,texqz,thb1,texqg,texgt,texhe;int mx=0,my=0,i=0,j=0,k=0,bcnt=16,jds=0,hqg=0,jiqiu=0;int leftm=0,rightm=0;GLfloat rx,ry,rz,speed=0;static GLfloat kx=0,ky=0,kz=0,zoom=300;static GLfloat anglex=0,angley=90,nowanglex=0,nowangley=0,nowatx=0,nowaty=0; static GLfloat at[6]={0.0,300.0,500.0,0.0,80.0,0.0};static GLfloat M=1,U=0.2,T=0.1,QR=5.715,G=-4;GLfloat m[16];//定义球及位置矢量结构体struct p3{GLfloat x;GLfloat y;GLfloat z;};struct myb{ struct p3 p;struct p3 v;struct p3 a;GLfloat mv;GLfloat ma;int jd;GLuint wl;} B[16];//函数申明int power_of_two(int n);GLuint load_texture(const char* file_name);void mydball(GLfloat mybr,GLuint BALL);void myinitball();void mycolide(int j,int k);void mybianyuan(int j);void myjindai(int j);void mylight(GLint lh,GLfloat lx,GLfloat ly,GLfloat lz,GLfloat lm);void renderoom(void);void renderqz(void);void myinitload();void myIdle(void);void myDisplay(void);static void key(unsigned char key,int x,int y);static void mymouse(int mbutton,int mstate,int x,int y);static void mymotion(int x,int y);void myhqg(GLfloat mspeed);void mystring(float x, float y, void *font, char* c);void myto2d();void myto3d();int main(int argc, char* argv[]){glutInit(&argc, argv);glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_STENCIL);glutInitWindowPosition(200, 100);glutInitWindowSize(WIDTH, HEIGHT);glutCreateWindow("OpenGL光照演示");glutFullScreen();myinitball();glutDisplayFunc(&myDisplay);glutKeyboardFunc(key); //设置键盘回调函数glutIdleFunc(&myIdle); //设置窗口刷新的回调函数glutMouseFunc(mymouse); //设置鼠标器按键回调函数glutMotionFunc(mymotion); //设置鼠标器移动回调函数mylight(L1,0,390,0,1); //光照模型glutMainLoop();return 0;}void myDisplay(void){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glMatrixMode(GL_PROJECTION);// 创建透视效果视图glLoadIdentity();gluPerspective(60.0f, 16.0/9, 1, 10000.0f);glTranslatef(kx,ky,kz);glMatrixMode(GL_TEXTURE);glLoadIdentity();glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(at[0],at[1],at[2],at[3],at[4],at[5], 0.0, 1.0, 0.0);renderoom();renderqz();for(i=0;i<bcnt;i++){if(B[i].jd==0){for (j=0; j < 15; j++) m[j] = 0.0;m[0] = m[5] = m[10] = 1.0;m[7] = (-1.0)/405;glPushMatrix();glTranslatef(B[i].p.x,B[i].p.y,B[i].p.z);glPushMatrix();glTranslatef(0, 400, 0);glMultMatrixf(m);glTranslatef(0, -400, 0);glDepthMask(GL_FALSE);glEnable (GL_BLEND);glColor4f(0.3,0.3,0.3,0.5);glBlendFunc(GL_SRC_ALPHA, GL_DST_COLOR);mydball(QR, texhe);glDisable (GL_BLEND);glDepthMask(GL_TRUE);glPopMatrix();glRotatef(B[i].ma, B[i].a.x, B[i].a.y, B[i].a.z);mydball(QR,B[i].wl);glPopMatrix();}else{glPushMatrix();glTranslatef(B[i].p.x,B[i].p.y,B[i].p.z);mydball(QR,B[i].wl);glPopMatrix();}}if(hqg==1) myhqg(speed);glutSwapBuffers();}void myIdle(void){GLfloat vx=0,vz=0;at[0]=zoom*(cos(anglex))+at[3];at[1]=zoom*(sin(angley))+at[4];at[2]=zoom*(sin(anglex))+at[5];for(i=0;i<bcnt;i++){if(B[i].jd==0){for(k=i+1;k<bcnt;k++) mycolide(i,k);//碰撞检测mybianyuan(i);myjindai(i);B[i].mv=pow(B[i].v.x,2)+pow(B[i].v.z,2);if(B[i].mv>0.1){B[i].mv=sqrt(B[i].mv);vx=B[i].v.x/B[i].mv;vz=B[i].v.z/B[i].mv;B[i].mv+=G*T;B[i].v.x=B[i].mv*vx;B[i].v.z=B[i].mv*vz;B[i].p.x+=B[i].v.x*T;B[i].p.z+=B[i].v.z*T;B[i].a.x=(-1)*vz;B[i].a.z=vx;B[i].ma+=-180*B[i].mv*T/(QR*PI);}else B[i].mv=0;}}if(hqg==1){if(speed>200) speed-=200;else speed+=2;}if(jiqiu==1){GLfloat atxy=0;atxy=sqrt(pow(at[3]-at[0],2)+pow(at[5]-at[2],2));B[0].v.x=speed*(at[3]-at[0])/atxy;B[0].v.z=speed*(at[5]-at[2])/atxy;jiqiu=0;speed=0;}if(leftm){B[0].v.x=0;B[0].v.z=0;speed=0;}myDisplay();}void myinitball(){GLfloat hhh;hhh=2*QR*sin(PI/3);B[0].p.x=0; B[0].p.y=80; B[0].p.z=-70;B[1].p.x=0; B[1].p.y=80; B[1].p.z=70;B[2].p.x=-3*QR; B[2].p.y=80; B[2].p.z=70.0+3.0*hhh;B[3].p.x=-1*QR; B[3].p.y=80; B[3].p.z=70+hhh;B[4].p.x=4*QR; B[4].p.y=80; B[4].p.z=70+4.0*hhh;B[5].p.x=2*QR; B[5].p.y=80; B[5].p.z=70+2.0*hhh;B[6].p.x=-2*QR; B[6].p.y=80; B[6].p.z=70+4.0*hhh;B[7].p.x=QR; B[7].p.y=80; B[7].p.z=70+3.0*hhh;B[8].p.x=0; B[8].p.y=80; B[8].p.z=70+2.0*hhh;B[9].p.x=2*QR; B[9].p.y=80; B[9].p.z=70+4.0*hhh;B[10].p.x=QR; B[10].p.y=80; B[10].p.z=70+hhh;B[11].p.x=-1*QR; B[11].p.y=80; B[11].p.z=70+3.0*hhh;B[12].p.x=0; B[12].p.y=80; B[12].p.z=70+4.0*hhh;B[13].p.x=-4*QR; B[13].p.y=80; B[13].p.z=70+4.0*hhh;B[14].p.x=-2*QR; B[14].p.y=80; B[14].p.z=70.0+2.0*hhh;B[15].p.x=3*QR; B[15].p.y=80; B[15].p.z=70+3.0*hhh;for(i=0;i<bcnt;i++){B[i].v.x=0; B[i].v.y=0; B[i].v.z=0;B[i].a.x=0; B[i].a.y=0; B[i].a.z=0;B[i].jd=0;B[i].mv=0;B[i].ma=0;}myinitload();}void mycolide(int j,int k){GLfloat rr,cx,cy,ccx,ccy,v1c,v1cc,v2c,v2cc;rr=sqrt(pow(B[k].p.x-B[j].p.x,2)+pow(B[k].p.z-B[j].p.z,2));if(rr<2*QR-1){PlaySound("audio/hit.wav", NULL, SND_FILENAME | SND_ASYNC);cx=(B[k].p.x-B[j].p.x)/rr;cy=(B[k].p.z-B[j].p.z)/rr;ccx=cy*(-1);ccy=cx;v1c=B[j].v.x*cx+B[j].v.z*cy;v1cc=B[j].v.x*ccx+B[j].v.z*ccy;v2c=B[k].v.x*cx+B[k].v.z*cy;v2cc=B[k].v.x*ccx+B[k].v.z*ccy;B[j].v.x=v1cc*ccx+v2c*cx;B[j].v.z=v1cc*ccy+v2c*cy;B[k].v.x=v1c*cx+v2cc*ccx;B[k].v.z=v1c*cy+v2cc*ccy;B[k].p.x=B[j].p.x+2*QR*cx;B[k].p.z=B[j].p.z+2*QR*cy;}}void mybianyuan(int j){if(abs(B[j].p.x)>72-2*QR ){if(B[j].p.x>0) B[j].p.x=72-2*QR;if(B[j].p.x<0) B[j].p.x=-72+2*QR;B[j].v.x*=(-1);}if(abs(B[j].p.z)>137-2*QR ){if(B[j].p.z>0) B[j].p.z=137-2*QR;if(B[j].p.z<0) B[j].p.z=-137+2*QR;B[j].v.z*=(-1);}}void myjindai(int j){GLfloat hhh;hhh=2*QR*sin(PI/3);if(sqrt(pow(B[j].p.x-(-65),2)+pow(B[j].p.z-(-135),2))<15 ||sqrt(pow(B[j].p.x-65,2)+pow(B[j].p.z-(-135),2))<15 ||sqrt(pow(B[j].p.x-(-65),2)+pow(B[j].p.z-135,2))<15 ||sqrt(pow(B[j].p.x-65,2)+pow(B[j].p.z-135,2))<15 ||sqrt(pow(B[j].p.x-(-70),2)+pow(B[j].p.z,2))<12 ||sqrt(pow(B[j].p.x-70,2)+pow(B[j].p.z,2))<12 ){if(j==0) {B[0].p.x=0; B[0].p.y=80; B[0].p.z=-70;}else if(j==8) {B[8].p.x=0; B[8].p.y=80; B[8].p.z=70+2.0*hhh;}else{B[j].jd=1;jds+=1;B[j].p.z=-100+jds*20;B[j].p.y=80;if(j>8) B[j].p.x=100;else B[j].p.x=-100;}B[j].v.x=0;B[j].v.y=0;B[j].v.z=0;}}static void key(unsigned char key,int x,int y){switch (key){case 27 :exit(0);case 'd' :case 'D' :if(kx>-490) kx-=10;break;case 'a':case 'A':if(kx<490) kx+=10;break;case 'w':case 'W':zoom-=10;if(zoom<10) zoom=10;break;case 's':case 'S':zoom+=10;if(zoom>500) zoom=500;break;}}static void mymouse(int mbutton,int mstate,int x,int y){mx=x;my=y;if(mbutton==GLUT_LEFT_BUTTON && mstate==GLUT_DOWN){ nowatx=kx;nowaty=ky;leftm=1;rightm=0;}else {leftm=0;}if(mbutton==GLUT_MIDDLE_BUTTON && mstate==GLUT_DOWN){at[3]=B[0].p.x; at[4]=B[0].p.y; at[5]=B[0].p.z; }if(mbutton==GLUT_RIGHT_BUTTON && mstate==GLUT_DOWN){nowanglex=anglex;nowangley=angley;leftm=0;rightm=1;hqg=1; }else {rightm=0;hqg=0;}if(mbutton==GLUT_RIGHT_BUTTON && mstate==GLUT_UP) jiqiu=1;else jiqiu=0;}static void mymotion(int x,int y){if(leftm) { kx=nowatx+x-mx; ky=nowaty+y-my; }if(rightm) {anglex=nowanglex+(x-mx)*0.01; angley=nowangley+(y-my)*0.01;} }void myinitload(){B[1].wl=load_texture("tex/B1.bmp");B[2].wl=load_texture("tex/B2.bmp");B[3].wl=load_texture("tex/B3.bmp");B[4].wl=load_texture("tex/B4.bmp");B[5].wl=load_texture("tex/B5.bmp");B[6].wl=load_texture("tex/B6.bmp");B[7].wl=load_texture("tex/B7.bmp");B[8].wl=load_texture("tex/B8.bmp");B[9].wl=load_texture("tex/B9.bmp");B[10].wl=load_texture("tex/B10.bmp");B[11].wl=load_texture("tex/B11.bmp");B[12].wl=load_texture("tex/B12.bmp");B[13].wl=load_texture("tex/B13.bmp");B[14].wl=load_texture("tex/B14.bmp");B[15].wl=load_texture("tex/B15.bmp");B[0].wl=load_texture("tex/B16.bmp");texGround=load_texture("tex/DB.bmp");texWall=load_texture("tex/wood.bmp");thb=load_texture("tex/thb2.bmp");thb1=load_texture("tex/thb1.bmp");texzb=load_texture("tex/zb.bmp");texqz=load_texture("tex/qz.bmp");texqg=load_texture("tex/QG.bmp");texgt=load_texture("tex/GT.bmp");texhe=load_texture("tex/black.bmp");}int power_of_two(int n){if( n <= 0 )return 0;return (n & (n-1)) == 0;}GLuint load_texture(const char* file_name){GLint width, height, total_bytes;GLubyte* pixels = 0;GLuint last_texture_ID, texture_ID = 0;FILE* pFile = fopen(file_name, "rb");if( pFile == 0 )return 0;fseek(pFile, 0x0012, SEEK_SET);fread(&width, 4, 1, pFile);fread(&height, 4, 1, pFile);fseek(pFile, BMP_Header_Length, SEEK_SET);{GLint line_bytes = width * 3;while( line_bytes % 4 != 0 ) ++line_bytes;total_bytes = line_bytes * height;}pixels = (GLubyte*)malloc(total_bytes);if( pixels == 0 ) {fclose(pFile); return 0;}if( fread(pixels, total_bytes, 1, pFile) <= 0 ) { free(pixels); fclose(pFile); return 0; } {GLint max;glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);if( !power_of_two(width) || !power_of_two(height) || width > max || height > max ){const GLint new_width = 256;const GLint new_height = 256; // 规定缩放后新的大小为边长的正方形GLint new_line_bytes, new_total_bytes;GLubyte* new_pixels = 0;new_line_bytes = new_width * 3;while( new_line_bytes % 4 != 0 )++new_line_bytes;new_total_bytes = new_line_bytes * new_height;new_pixels = (GLubyte*)malloc(new_total_bytes);if( new_pixels == 0 ) { free(pixels); fclose(pFile); return 0; }gluScaleImage(GL_RGB,width, height, GL_UNSIGNED_BYTE, pixels,new_width, new_height, GL_UNSIGNED_BYTE, new_pixels);free(pixels);pixels = new_pixels;width = new_width;height = new_height;}}glGenTextures(1, &texture_ID);if( texture_ID == 0 ) { free(pixels); fclose(pFile); return 0; }glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture_ID);glBindTexture(GL_TEXTURE_2D, texture_ID);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEA T);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);glBindTexture(GL_TEXTURE_2D, last_texture_ID);free(pixels);return texture_ID;}void mylight(GLint lh,GLfloat lx,GLfloat ly,GLfloat lz,GLfloat lm){glPushMatrix();{/********* 光照处理**********/GLfloat light_ambient[] = { 0.5, 0.5, 0.5, 1 };GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1 };GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };GLfloat light_position0[] = { lx, ly, lz ,lm }; //定义光位置得齐次坐标(x,y,z,w),如果w=1.0,为定位光源(也叫点光源),如果w=0,为定向光源(无限光源),定向光源为无穷远点,因而产生光为平行光。

opengl简单入门实例

opengl简单入门实例

opengl简单⼊门实例实现任务⽬标:使⽤纹理贴图,增强可视效果应⽤坐标变换,实现场景中不同物体重建采⽤双缓冲技术,实现场景实时绘制具有⼀定的⿏标、键盘交互功能先放效果⿏标的交互功能有:右键暂停转动,左键继续转动,滚轮向前放⼤,向后缩⼩IDE:opengl实现需要库函数。

⽤的编译环境是visual studio。

附上⼀个很好的教程【1】:。

(vs2019也可以⽤)⼀个很好的⼊门教程【2】:。

讲得很仔细,通俗易懂。

前⼏课⽤到的库都没有超过glut的范围。

事实上,对于opengl的实现主要是对于各种库函数的调⽤,所以对于各种库函数的认知很重要。

这⾥也给出⼀个很好的教程【3】:。

ok,在看了上⾯的教程以后肯定对于opengl有了⼀定认识,尤其是第⼆个教程中讲解得⾮常仔细。

所以本⽂接下来的内容是建⽴在对那个教程的学习基础之上,对⼀些我在实践中遇到的问题作出补充。

下⾯就进⼊正⽂。

所包含的头⽂件⽬录1 #include <GL/glut.h>2 #include <stdlib.h>3 #include <stdio.h>最基本的功能是当然是创建⾃⼰的图形并显⽰出来,如上图我创建的是⽇地⽉系统。

需要的函数为display()和main()。

这其中很重要的⼀个知识点就是图像的视图变换/模型变换、投影变换和视⼝变换。

有关这块的内容个⼈觉得教程【2】中讲得不够清楚,可以参考⼀些别的教程。

⽐如:;。

这⾥要介绍⼀下opengl中的坐标轴。

x轴⽔平向右为正,y轴竖直向上为正,z轴垂直屏幕向外为正。

符合右⼿定则。

2020/5/15 13:06:37 对于图像的各种变换做⼀个⼩的补充视图变换即设置/改变观察点的位置,可以这么理解,相当于选择⼀个位置和⽅向设置⼀台照相机。

针对glLookAt()函数⽽⾔,它⼀共有九个参数,3对坐标值。

第⼀对三维坐标是观察点(照相机)在世界坐标中的位置,第⼆对三维坐标是被观察点(物体)的位置。

opengl 割圆法

opengl 割圆法

Opengl割圆法OpenGL 中的割圆法通常指的是割圆插值法(Gouraud Shading),也被称为梯度三角形插值法。

这种插值方法用于在三角形中计算像素的颜色值,其中每个像素的颜色取决于三角形顶点的颜色和顶点到像素中心的向量。

具体来说,割圆插值法的计算过程如下:确定三角形三个顶点的颜色值。

这些颜色值通常由顶点着色器提供。

计算像素中心到三角形每个顶点的向量。

这些向量可以用于计算像素点在三角形内的位置。

根据像素中心到三角形每个顶点的向量,使用割圆插值法计算像素的颜色值。

具体计算方法是将顶点颜色和对应的向量权重相加,得到像素颜色。

下面是一个简单的示例代码,展示了如何在OpenGL 中使用割圆插值法计算像素颜色:c// 假设已经获取了三角形三个顶点的颜色值和像素中心到顶点的向量GLfloat color1[3] = {1.0, 0.0, 0.0}; // 顶点1的颜色GLfloat color2[3] = {0.0, 1.0, 0.0}; // 顶点2的颜色GLfloat color3[3] = {0.0, 0.0, 1.0}; // 顶点3的颜色GLfloat vertexPos1[3] = {0.0, 0.0, 0.0}; // 顶点1的坐标GLfloat vertexPos2[3] = {1.0, 0.0, 0.0}; // 顶点2的坐标GLfloat vertexPos3[3] = {0.0, 1.0, 0.0}; // 顶点3的坐标GLfloat pixelPos[3] = {0.5, 0.5, 0.0}; // 像素中心坐标// 计算像素颜色GLfloat weight1 = (vertexPos2[0] - pixelPos[0]) * (vertexPos2[1] - pixelPos[1]) / ((vertexPos2[0] - pixelPos[0]) * (vertexPos2[1] - vertexPos1[1]) + (vertexPos2[0] - vertexPos1[0]) * (pixelPos[1] - vertexPos2[1]));GLfloat weight2 = (vertexPos3[0] - pixelPos[0]) * (vertexPos3[1] - pixelPos[1]) / ((vertexPos3[0] - pixelPos[0]) * (vertexPos3[1] - vertexPos2[1]) + (vertexPos3[0] - vertexPos2[0]) * (pixelPos[1] - vertexPos3[1]));GLfloat weight3 = 1.0 - weight1 - weight2;GLfloat pixelColor[3];pixelColor[0] = color1[0] * weight1 + color2[0] * weight2 + color3[0] * weight3;pixelColor[1] = color1[1] * weight1 + color2[1] * weight2 + color3[1] * weight3;pixelColor[2] = color1[2] * weight1 + color2[2] * weight2 + color3[2] * weight3;在上述代码中,我们首先定义了三角形三个顶点的颜色值和像素中心到顶点的向量。

一个简单的案例_OpenGL ES 3.x游戏开发(上卷)_[共3页]

一个简单的案例_OpenGL ES 3.x游戏开发(上卷)_[共3页]

第15章 Web端3D游戏开发——WebGL 3D应用开发40815.4.1 一个简单的案例首先本小节将在上一节案例的基础上进一步升级,给茶壶加上纹理贴图,升级后的案例Sample15_3运行效果如图15-9所示。

▲图15-9 案例Sample15_3的运行效果说明从图15-9中可以看出,本节的案例中由于加入了纹理贴图,因此,渲染的效果比上一节案例有了进一步的提高。

了解了本小节案例的运行效果后,下面就可以进行本小节案例的开发了。

由于本案例中绝大部分代码与上一节案例中的相同,因此,这里仅给出不同的部分,主要包括ObjObject.js脚本中增加的代码、GLUtil.js脚本中增加的加载纹理图的相关函数,以及案例中增加了一个pic文件夹等,其具体内容如下。

(1)首先介绍的是声明ObjObject类的JavaScript脚本—ObjObject.js,其具体代码如下。

代码位置:见本书随书中源代码/第15章/Sample15_3/js目录下的ObjObject.js文件。

1 function ObjObject( //声明绘制用物体对象所属类2 gl, //GL上下文3 vertexDataIn, //顶点坐标数据4 vertexNormalIn, //顶点法向量数据5 vertexTexCoorIn, //顶点纹理坐标数据6 programIn //着色器程序id7 ){8 ……//此处省略了与上一个案例相同的代码,读者可自行查看随书中的源代码9 this.vertexTexCoor=vertexTexCoorIn; //初始化顶点纹理坐标数据10 this.vertexTexCoorBuffer=gl.createBuffer(); //创建顶点纹理坐标数据缓冲11 gl.bindBuffer(gl.ARRAY_BUFFER,this.vertexTexCoorBuffer);//绑定顶点纹理坐标数据缓冲12 //将顶点纹理坐标数据送入缓冲13 gl.bufferData(gl.ARRAY_BUFFER,new Float32Array(this.vertexTexCoor),gl.STATIC_DRAW);14 this.program=programIn; //初始化着色器程序id15 this.drawSelf=function(ms,texture){ //绘制物体的方法16 ……//此处省略了与上一个案例相同的代码,读者可自行查看随书的源代码17 //启用顶点纹理坐标数据数组18 gl.enableVertexAttribArray(gl.getAttribLocation(this.program,"aTexCoor"));19 gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexTexCoorBuffer);//绑定顶点纹理坐标数据缓冲20 //给管线指定顶点纹理坐标数据21 gl.vertexAttribPointer(gl.getAttribLocation(this.program,"aTexCoor"),2,gl.FLOAT,false,0,0);22 gl.bindTexture(gl.TEXTURE_2D, texture); //绑定纹理23 //指定采样器对应的纹理单元24 gl.uniform1i(gl.getUniformLocation(this.program, "sTexture"),0);25 gl.drawArrays(gl.TRIANGLES, 0, this.vcount); //用顶点法绘制物体26 }}。

  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到底是怎么一回事。

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

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

相关文档
最新文档