opengl入门

来源:互联网 发布:软件测试经理招聘 编辑:程序博客网 时间:2024/05/17 06:37
  • 参考: kiya-z OpenGL系列
  • 我的OpenGL里很多东西都是参考他的
  • 参考OpenGL 中 GLUT 消息事件处理函数

Glut模板

  • 初模位大窗显循 背帧开结刷
  • #pragma comment (lib, “gl.lib”) //gcc部支持内部连接库
//#include "stdafx.h"//#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"") //这句是不让控制台窗体出现,如果想要出现,去掉即可。//#pragma comment (lib, "opengl32.lib")//#pragma comment (lib, "glu32.lib")//#pragma comment (lib, "glaux.lib")//#pragma comment (lib, "glut32.lib")//Windows VC6.0环用//#pragma comment (lib, "gl.lib")//#pragma comment (lib, "glu.lib")//#pragma comment (lib, "glut.lib") //Windows环境用#include <GL/glut.h>#include <stdio.h>#include <stdlib.h>#include <math.h>const double PI = acos(-1.0);void myDraw(GLfloat Pos[2], GLfloat Length){}void display(){    glClearColor(0, 1, 1, 0);    glClear(GL_COLOR_BUFFER_BIT);    glBegin(GL_LINES);    float pCenter[] = {200.0, 200.0};    myDraw(pCenter, 100.0);    glEnd();    glFlush();}int main(int argc, char* argv[]) //main(int argc, char **argv){    glutInit(&argc, argv);    glutInitDisplayMode(GLUT_DEPTH | GLUT_SINGLE | GLUT_RGB);    glutInitWindowPosition(300, 300);    glutInitWindowSize(500, 500);    glutCreateWindow("example");    //gluOrtho2D(0, 600, 0, 600);    glutDisplayFunc(display);    glutMainLoop();    return 0;}

pragma

  • #pragma comment(linker, “/subsystem:\”windows\” /entry:\”mainCRTStartup\”“) //作用是去掉执行时必须出现的控制台窗口
  • 操作系统装载应用程序后,做完初始化工作就转到程序的入口点执行。程序的默认入口点实际上是由连接程序设置的,不同的连接器选择的入口函数也不尽相同。
  • 在VC下,连接器对控制台程序设置的入口函数是 mainCRTStartup,mainCRTStartup 再调用你自己编写的 main 函数;对图形用户界面(GUI)程序设置的入口函数是 WinMainCRTStartup,WinMainCRTStartup 调用你自己写的 WinMain 函数。具体设置哪个入口点是由连接器的“/subsystem:”选项参数确定的,它告诉操作系统如何运行编译生成的.EXE文件。
  • 可以指定四种方式:“CONSOLE|WINDOWS|NATIVE|POSIX”如果这个选项参数的值为“WINDOWS”,则表示该应用程序运行时不需要控制台,
  • 有关连接器参数选项的详细说明请参考 MSDN 库。

main 初始化

  • glutInit(&argc, argv); //责初始化GLUT,在任何的GLUT函数和OpenGL函数调用之前,必须先调用此函数来进行初始化
  • //至于这个参数的用途,就得看你程序怎么写了。比如说一个播放器,你直接双击运行它就只是运行EXE文件,不执行其它操作,如果你拖一个视频到播放器的图标上,那么在运行EXE后它还会自动打开这个视频文件进行播放。
  • glutInitDisplayMode(unsighed int mode) //其中GLUT_RGB表示使用RGB颜色,与之对应的还有GLUT_INDEX(表示使用索引颜色)。
  • //GLUT_SINGLE 表示使用单缓冲,与之对应的还有 GLUT_DOUBLE(使用双缓冲)。等等
  • glutInitWindowPositon(int x,int y) //设置窗口在屏幕中的位置, X: 距离屏幕左边的像素数。-1是默认值
  • glutInitWindowSize(int width,int height) //设置窗口的大小
  • glutCreateWindow(“example”); //在屏幕上创建一个窗口,窗口的默认大小是300x300像素,在屏幕上面的默认显示位置是在屏幕的左上角, 根据前面设置的信息创建窗口。参数将被作为窗口的标题。注意:窗口被创建后,并不立即显示到屏幕上。需要调用 glutMainLoop 才能看到窗口。
  • glutDisplayFunc(display); //负责注册回调函数,通过该函数注册的回调函数,在OpenGL确定需要进行重绘时,就会调用该函数注册的显示回调函数
  • //函数原型: void glutReshapeFunc(void(*func)(int width,int height)); func: 指负责设置正确投影的函数的名称
  • glutMainLoop(); //使程序进入无限事件循环(例如窗口事件发生调用),在函数要作为main函数的最后一条语句出现, 只需要知道这个函数可以显示窗口,并且等待窗口关闭后才会返回

常用的GLUT回调函数

  • 显示(Display): void glutDisplayFunc(void (*func)(void))
  • 窗口发生改变(Reshape): void glutReshapeFunc(void (*func)(int width, int height)) 下面的五角星中用到了
  • 键盘(Keyboard):void glutKeyboardFunc(void (*func)(unsigned int key, int x, int y))
  • 鼠标(Mouse):void glutMouseFunc(void (*func)(int button, int state, int x, int y))
  • 鼠标按键并移动(Motion)[拖动]: void glutMotionFunc (void (*func)(int x, int y))
  • 后台处理: void glutIdleFunc(void (*func)(void))
  • glutIdleFunc && auxIdleFunc(randomChange); //空闲管理及处理函数, aux库过时了,最好别用
  • glutReshapeFunc(Reshape); //重新建立用作新渲染画布的矩形区域,定义绘制物体时使用的坐标系, 此外这个函数还会在窗口初次被创建时调用,保证初始化窗口不是正方形的时候渲染也不会变形出错。

Reshape

void Reshape(int w,int h){    glViewport(0,0,(GLsizei)w,(GLsizei)h);    glMatrixMode(GL_PROJECTION);    glLoadIdentity();    gluOrtho2D(0.0,(GLdouble)w,0.0,(GLdouble)h);}
glViewport:glViewport是OpenGL中的一个函数。
  • 计算机图形学中,在屏幕上打开窗口的任务是由窗口系统,而不是OpenGL负责的。在默认情况下,视口被设置为占据打开窗口的整个像素矩形,窗口大小和设置视口大小相同,所以为了选择一个更小的绘图区域,就可以用glViewport函数来实现这一变换,在窗口中定义一个像素矩形,最终将图像映射到这个矩形中。例如可以对窗口区域进行划分,在同一个窗口中显示分割屏幕的效果,以显示多个视图。
  • glViewport(GLint x,GLint y,GLsizei width,GLsizei height)为其函数原型。
  • X,Y————以像素为单位,指定了视口的左下角(在第一象限内,以(0,0)为原点的)位置。
  • width,height————表示这个视口矩形的宽度和高度,根据窗口的实时变化重绘窗口。
glMatrixMode(Mode) : 指定哪一个矩阵是当前矩阵
  • mode 指定哪一个矩阵堆栈是下一个矩阵操作的目标,可选值:
  • GL_MODELVIEW,对模型视景矩阵堆栈应用随后的矩阵操作
  • GL_PROJECTION,对投影矩阵应用随后的矩阵操作
  • GL_TEXTURE,对纹理矩阵堆栈应用随后的矩阵操作
  • 与glLoadIdentity()一同使用
  • 如果参数是GL_PROJECTION,这个是投影的意思,就是要对投影相关进行操作,也就是把物体投影到一个平面上,就像我们照相一样,把3维物体投到2维的平面上。这样,接下来的语句可以是跟透视相关的函数,比如glFrustum()或gluPerspective();
glLoadIdentity(): 该函数的功能是重置当前指定的矩阵为单位矩阵。
  • OpenGL为我们提供了一个非常简单的恢复初始坐标系的手段,那就是调用glLoadIdentity()命令。该命令是一个无参的无值函数,其功能是用一个4×4的单位矩阵来替换当前矩阵,实际上就是对当前矩阵进行初始化。也就是说,无论以前进行了多少次矩阵变换,在该命令执行后,当前矩阵均恢复成一个单位矩阵,即相当于没有进行任何矩阵变换状态。
  • 单位矩阵就是对角线上都是1,其余元素皆为0的矩阵。当调用glLoadIdentity()之后,实际上将当前点移到了屏幕中心:类似于一个复位操作
  • X坐标轴从左至右,Y坐标轴从下至上,Z坐标轴从里至外。
  • OpenGL屏幕中心的坐标值是X和Y轴上的0.0f点。
  • 中心左面的坐标值是负值,右面是正值。
  • 移向屏幕顶端是正值,移向屏幕底端是负值。
  • 移入屏幕深处是负值,移出屏幕则是正值。
  • 需要注意的是,用单位矩阵替换当前矩阵并不改变当前矩阵模式。
  • 应当说明的是,用一个单位矩阵来替换当前矩阵的做法并非在任何场合下都可以使用
  • 例如,已经进行了3次矩阵变换,而现在打算将当前矩阵恢复到第二次变换后的状态时,该方法将失效。此时可用glPushMatrix()命令将每次变换前的矩阵压入矩阵堆栈,在进行完新矩阵中的各种操作后,再利用glPopMatrix()命令将栈顶的矩阵弹出矩阵堆栈,成为当前矩阵。
glOrtho: 设置或修改修剪空间的范围
  • void glOrtho(GLdouble left,GLdouble right,GLdouble bottom,GLdouble top,GLdouble near,GLdouble far)
  • gluOrtho2D(0, 400, 0, 400); //参数分别代表(左下角x坐标,右上角x坐标,左下角y坐标,右上角y坐标)——坐标全相对于窗口左下角--原点),near和far默认为-1和1,此函数决定一个平行六面体
  • 使用glOrtho函数可以将当前的可视空间设置为正投影空间。如果绘制的图空间本身就是二维的,可以使gluOrtho2D.他的使用类似于glOrtho.
  • glOrtho就是一个正射投影函数。它创建一个平行视景体。实际上这个函数的操作是创建一个正射投影矩阵,并且用这个矩阵乘以当前矩阵。
  • 其中近裁剪平面是一个矩形,
  • 矩形左下角点三维空间坐标是(left,bottom,-near),右上角点是(right,top,-near);
  • 远裁剪平面也是一个矩形,左下角点空间坐标是(left,bottom,-far),右上角点是(right,top,-far)。
  • 所有的near和far值同时为正或同时为负。
  • 如果没有其他变换,正射投影的方向平行于Z轴,且视点朝向Z负轴。这意味着物体在视点前面时far和near都为负值,物体在视点后面时far和near都为正值。
  • 假设有一个球体,半径为1,圆心在(0, 0, 0),那么
  • 我们设定glOrtho(-1.5, 1.5, -1.5, 1.5, -10, 10);就表示用一个宽高都是3的框框把这个球体整个都装了进来。
  • 如果设定glOrtho(0.0, 1.5, -1.5, 1.5, -10, 10);就表示用一个宽是1.5, 高是3的框框把整个球体的右面装进来;
  • 如果设定glOrtho(0.0, 1.5, 0.0, 1.5, -10, 10);就表示用一个宽和高都是1.5的框框把球体的右上角装了进来。
  • 暂时理解为表示视角的位置


  • 这是另一个的Reshape, 慢慢参透

  • if (h == 0) h = 1;
  • printf(“%d, %d\n”, w, h);
  • float ratio = 1.0 * w / h; //计算高宽比(wight/height)。注意为了计算正确,我们必须保证高度不为0。(你可以设置窗口宽度为0).
  • glMatrixMode(GL_PROJECTION); // 单位化投影矩阵, 我们设置当前矩阵为投影矩阵,这个矩阵定义了一个可视空间(viewing volume)
  • glLoadIdentity();
  • glViewport(0, 0, w, h); //设置视口大小为整个窗口大小,然后我们用函数glViewport把视口设置为整个窗口。函数中(0,0)指定了视口的左下角,(w,h)指定了视口矩形的大小, 从Reshape(int w, int h)中传递过来。
  • gluPerspective(45, ratio, 1, 1000); // 设置正确的投影矩阵
  • glMatrixMode(GL_MODELVIEW); // 设置模型视图矩阵
  • glLoadIdentity();
  • gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, -1.0, 0.0f, 1.0f, 0.0f);
  • 上边那些还不太懂… 第三篇博客 OpenGL—GLUT教程(三) GLUT窗口设置
  • display(); //不加这个的话,拖动窗口会变形,但中心点不变

Clear Flush Finish

  • glClearColor(0, 1.0, 0, 0); //glclearColor()中的四个参数中,前三个分别代表红、绿、蓝所占的分量,范围从0.0f~1.0f,最后一个参数是透明度Alpha值,范围也是0.0f~1.0f。
  • glClear(GL_COLOR_BUFFER_BIT); //清除帧缓存, 并将每个像素对应单元赋为设置背景颜色值
  • //GL_COLOR_BUFFER_BIT: 当前可写的颜色缓冲
  • //GL_DEPTH_BUFFER_BIT: 深度缓冲
  • //GL_ACCUM_BUFFER_BIT: 累积缓冲
  • //GL_STENCIL_BUFFER_BIT: 模板缓冲
  • glFinish(); //表示结束绘图命令,使用单缓存时必须要。双缓冲时可以不要。
  • glFlush(); //保证前面的 OpenGL 命令立即执行(而不是让它们在缓冲区中等待)。其作用跟 fflush(stdout)类似。
  • auxSwapBuffers(); //双缓存时使用。交换缓存命令,表示当前显示帧和下帧的帧缓存交换

glShadeModel

  • glShadeModel(GL_FLAT);//GL_FLAT为默认mode,可省略
  • //GL_FLAT,则多边形的颜色取决于最后一个点。唯一例外是GL_POLYGON图元,它采用的是第一个顶点的颜色。
  • //GL_SMOOTH,则多边形被分割为多个三角形,然后进行平滑着色。从各个顶点给三角形投上光滑的阴影,为各个顶点指定的颜色之间进行插值

glBegin glEnd 及 中间的画图函数

  • glBegin(GL_POLYGON); //限定了一组或多组图元的定点定义
  • //OpenGL 要求:指定顶点的命令必须包含在 glBegin 函数之后,glEnd 函数之前(否则指定的顶点将被忽略)。并由 glBegin 来指明如何使用这些点。
  • //参数也可以是GL_LINE_STRIP(四个点画三边,不闭合), GL_LINE_LOOP(四个点画闭合四边形), GL_LINES(四个点画两条线)
  • //GL_POINTS:把每一个顶点作为一个点进行处理,顶点n即定义了点n,共绘制N个点
  • //GL_LINES:把每一个顶点作为一个独立的线段,顶点2n-1和2n之间共定义了n条线段,总共绘制N/2条线段
  • //GL_LINE_STRIP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,第n和n+1个顶点定义了线段n,总共绘制n-1条线段
  • //GL_LINE_LOOP:绘制从第一个顶点到最后一个顶点依次相连的一组线段,然后最后一个顶点和第一个顶点相连,第n和n+1个顶点定义了线段n,总共绘制n条线段
  • //GL_TRIANGLES:把每个顶点作为一个独立的三角形,顶点3n-2、3n-1和3n定义了第n个三角形,总共绘制N/3个三角形
  • //GL_TRIANGLE_STRIP:绘制一组相连的三角形,对于奇数n,顶点n、n+1和n+2定义了第n个三角形;对于偶数n,顶点n+1、n和n+2定义了第n个三角形,总共绘制N-2个三角形
  • //GL_TRIANGLE_FAN:绘制一组相连的三角形,三角形是由第一个顶点及其后给定的顶点确定,顶点1、n+1和n+2定义了第n个三角形,总共绘制N-2个三角形
  • //GL_QUADS:绘制由四个顶点组成的一组单独的四边形。顶点4n-3、4n-2、4n-1和4n定义了第n个四边形。总共绘制N/4个四边形
  • //GL_QUAD_STRIP:绘制一组相连的四边形。每个四边形是由一对顶点及其后给定的一对顶点共同确定的。顶点2n-1、2n、2n+2和2n+1定义了第n个四边形,总共绘制N/2-1个四边形
  • //GL_POLYGON:绘制一个凸多边形。顶点1到n定义了这个多边形。
  • glEnd(); //对应与glBegin();可以结束LOOP的绘制
  • 在他们之间可以调用的函数有:
  • glVertex*() 设置顶点坐标
  • glColor*() 设置当前颜色
  • glIndex*() 设置当前颜色表
  • glNormal*() 设置法向坐标
  • glEvalCoord*() 产生坐标
  • glCallList(),glCallLists() 执行显示列表
  • glTexCoord*() 设置纹理坐标
  • glEdgeFlag*() 控制边界绘制
  • glMaterial*() 设置材质

不在glBegin中间的画图函数

  • glRectf(-0.9f, 0.0f, 0.0f, 0.9f); //分别是左下角和右上角两点坐标
  • glPointSize(5); //表示点的像素
  • glLineWidth(5); //表示线的宽度

glVertex

  • 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); //如果第三个参数没有指定,则默认为0.0f
  • (四)glVertex4f(1.0f, 3.0f, 0.0f, 1.0f); //如果第四个参数没有指定,则默认为1.0f
  • (五)GLfloat VertexArr3[] = {1.0f, 3.0f, 0.0f}; glVertex3fv(VertexArr3);

其他

OpenGl的glMatrixMode()函数

glMatrixMode - 指定哪一个矩阵是当前矩阵。
模型视景矩阵,投影矩阵,纹理矩阵(在哪个模式下操作,就在哪个模式下操作)

  • GL_MODELVIEW,对模型视景矩阵堆栈应用随后的矩阵操作.(观察模式默认)
  • GL_PROJECTION,对投影矩阵应用随后的矩阵操作.(正交投影 gluOrtho2D 裁剪)
  • GL_TEXTURE,对纹理矩阵堆栈应用随后的矩阵操作.

在操作投影矩阵以前,需要调用函数:
glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影矩阵
glLoadIdentity(); //然后把矩阵设为单位矩阵
然后调用glFrustum()或gluPerspective(),它们生成的矩阵会与当前的矩阵相乘,生成透视的效果;

如.要使用透视(3D).那么先要设置透视投影glMatrixMode(GL_PROJECTION); //切换到投影矩阵.//...设置透视投影设置完成后开始画图,需要切换到 模型视图矩阵 才能正确画图.glMatrixMode(GL_MODELVIEW);// 画一个物体A (看起来是3D的),// 如这时候需画一个 2D效果 的 物体A,那么又需要透视投影glMatrixMode(GL_PROJECTION); //切换到投影矩阵..// ..设置正交投影  gluOrtho2D//..设置完成,切换回模型视图矩阵.....glMatrixMode(GL_MODELVIEW);// 再画一个物体A (看起来是2D的)// 如从头到尾都是画3D/2D, 只需初始化时设置一次.// 如果有交替,那么就需要glMatrixMode() 切换// 因这样设置很烦人,所以又有glPushMatrix() 保存当前矩阵

几何变换glTranslatef,glRotatef,glScalef执行变换函数时,会将系统的几何变换矩阵乘以变换函数对应的变换矩阵,乘的结果赋给系统几何变换矩阵
glLoadIdentity ( ) 将系统的几何变换矩阵(几何变换平移 旋转等)设置为单位阵

#include<GL/glut.h>class wcPt2D{public:    GLfloat x, y;};void init(void){    glClearColor(1.0, 1.0, 1.0, 0.0);    glMatrixMode(GL_PROJECTION);    gluOrtho2D(-100.0, 100.0, -100.0, 100.0);    glMatrixMode(GL_MODELVIEW);   //在不同的矩阵下进行操作}void triangle(wcPt2D *verts){    GLint k;    glBegin(GL_TRIANGLES);    for (k = 0; k < 3; k++)        glVertex2f(verts[k].x, verts[k].y);    glEnd();}void displayFcn(void){    wcPt2D verts[3] = {{ -50.0, -25.0}, {50.0, -25.0}, {0.0, 50.0}};    glClear(GL_COLOR_BUFFER_BIT);    glColor3f(0.0, 0.0, 1.0);    glViewport(0, 0, 300, 300); //视口定义函数    triangle(verts);    glColor3f(1.0, 0.0, 0.0);    glLoadIdentity();    glViewport(300, 0, 300, 300); //视口定义函数    glRotatef(90.0, 0.0, 0.0, 1.0);    triangle(verts);    glFlush();}int main(int argc, char* argv[]){    glutInit(&argc, argv);    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);    glutInitWindowPosition(50, 50);    glutInitWindowSize(600, 300);    glutCreateWindow("Split_Screen Example");    init();    glutDisplayFunc(displayFcn);    glutMainLoop();}
0 0