本节是OpenGL学习的第一个课时,下面介绍如何初始化一个窗体:
(1)显示一个有蓝色背景的窗体:
#include <GL/glut.h> #include <stdlib.h> void display(void) { /* clear all pixels */ glClear (GL_COLOR_BUFFER_BIT); glFlush (); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB); glutInitWindowSize (250, 250); glutInitWindowPosition (100, 100); glutCreateWindow ("蓝色背景窗体"); glClearColor (0.0, 0.0, 1.0, 0.0); glutDisplayFunc(display); glutMainLoop(); return 0; }
代码解释:
Several routines perform tasks necessary for initializing a window:
1) glutInit(int *argc, char **argv)
initializes GLUT and processes any command,line arguments (for X, this would be options such as -display and -geometry). glutInit() should be called before any other GLUT routine.
2)glutInitDisplayMode(unsigned int mode)
specifies whether to use an RGBA or color-index color model. You can also specify whether you want a single- or double-buffered window. (If you’re working in colorindex mode, you’ll want to load certain colors into the color map; use glutSetColor() to do this.) Finally, you can use this routine to indicate that you want the window to have an associated depth, stencil, multisampling, and/or accumulation buffer. For example, if you want a window with double buffering, the RGBA color model, and a depth buffer, you might call glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH).
3)glutInitWindowPosition(int x, int y)
specifies the screen location for the upper-left corner of your window.
4)glutInitWindowSize(int width, int height)
specifies the size, in pixels, of your window.
5)glutInitContextVersion(int majorVersion, int minorVersion)
specifies which version of OpenGL you want to use. (This is a new addition available only when using Freeglut, and was introduced with OpenGL Version 3.0. See “OpenGL Contexts” on page 27 for more details on OpenGL contexts and versions.)
6)glutInitContextFlags(int flags)
specifes the type of OpenGL context you want to use. For normal OpenGL operation, you can omit this call from your program. However, if you want to use a forward-compatible OpenGL context, you will need to call this routine. (This is also a new addition available only in Freeglut, and was introduced with OpenGL Version 3.0. See “OpenGL Contexts” on page 27 for more details on the types of OpenGL contexts.)
7)int glutCreateWindow(char *string)
creates a window with an OpenGL context. It returns a unique identifier for the new window. Be warned: until glutMainLoop() is called, the window is not yet displayed.
低级win32 api初始化一个窗体是比较复杂的,glut库简化了这个过程。
回调函数:
即win32的消息循环系统。
1)glutDisplayFunc调用一个函数,该函数会不断的被调用。
2)glutMainLoop用于启动程序,并使程序不断在运行,不退出,即进入消息循环。
3)glClearColor用于清除缓冲区颜色,并重新设置新的颜色。
4)guFlush刷新OpenGl命令队列,如果不调用此方法,那么重新绘制的图形将无法显示。
(2)显示一个带有白色矩形黑色背景的窗体:
//该程序的作用是在一个黑色的窗口中央画一个白色的矩形。 #include <GL/glut.h> //GLUT的头文件(本来OpenGL程序一般还要包含<GL/gl.h>和<GL/glu.h>,但GLUT的头文件中已经自动将这两个文件包含了,不必再次包含。) //注意函数名的大小写 void myDisplay() //这种gl开头的函数是OpenGL的标准函数 { glClear(GL_COLOR_BUFFER_BIT); //9.清除操作。GL_COLOR_BUFFER_BIT表示清除颜色。glClear还可以用来清除其他东西。 glRectf(-0.5,-0.5f,0.5f,0.5f); //10.画一个矩形。四个参数代表位于对角线的两个点的横纵坐标。 glFlush(); //11.保证前面的OpenGL命令能够立即执行,而不是在缓冲区等待。(作用跟fflush(stdout)类似) } int main(int argc, char *argv[]) //这种以glut开头的函数都是GLUT工具包所提供的函数 { glutInit(&argc, argv); //1.对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次。 glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE); //2.设置显示方式。GLUT_RGB表示使用RGB颜色,GLUT_INDEX表示使用INDEX(索引颜色);GLUT_SINGLE表示使用单缓冲,GLUT_DOUBLE(使用双缓冲)。 glutInitWindowPosition(100,100); //3.设置窗口在屏幕中的位置。 //4.glutInitWindowSize设置窗口的大小 glutCreateWindow("黑色的背景白色的矩形"); //5.根据前面的信息创建窗口,标题为设置的参数。 glutDisplayFunc(&myDisplay); //6.当需要画图的时候,这个函数就被调用.(寄存回调) glutMainLoop(); //7.当窗口被创建时,并不立即显示在屏幕上。这个函数有将窗口显示在屏幕上的作用。进行一个消息循环,当窗口关闭时这个函数才会返回。 return 0; } //8.当需要画图时,我们在glutDisplayFunc()中设置了“当需要画图时,调用myDisplay函数”。myDisplay用来画图,下面介绍myDisplay中的函数。
(3)详解:
1)glutInitDisplayMode()函数:
函数的功能是:设置显示方式;
函数原型是:void glutInitDisplayMode(unsigned int mode);
1.mode参数是一个GLUT库里预定义的可能的布尔组合。可以使用mode去指定颜色模式,数量和缓冲区类型。
下面是是mode的所有可能取值:
2.像素颜色在图形硬件中的存储方式有两种:RGBA和INDEX(像素索引)。
RGB色彩模式:是工业界的一种颜色标准,是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。 RGBA在RGB的基础上多了控制alpha透明度的参数。以上R、G、B三个参数,正整数值的取值范围为:0 - 255。百分数值的取值范围为:0.0% - 100.0%。超出范围的数值将被截至其最接近的取值极限。并非所有浏览器都支持使用百分数值。A参数,取值在0~1之间,不可为负值。
INDEX色彩模式:采用一个颜色表存放并索引图像中的颜色。如果原图像中的一种颜色没有出现在查照表中,程序会选取已有颜色中最相近的颜色或使用已有颜色模拟该种颜色。能减小文件大小,同时保持视觉上的品质不变。
3.设置单缓冲区或双缓冲区窗口:
GLUT_SINGLE:单缓冲区窗口,当不需要用户交互时用单缓冲,需要用户交互时要用双缓冲。
GLUT_DOUBLE:双缓冲区窗口,这是产生流畅动画必须选的。Glut使用双缓冲只需要在显示回调函数中使用函数glutSwapBuffers()取代glFlush()。
2)glClear()与glClearColor()函数:
glClear函数原型:void glClear(GLbitfield mask);
GLbitfield:可以使用|运算符组合不同的缓冲标志位,表明需要清除的缓冲。
(例如glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)表示要清除颜色缓冲以及深度缓冲)
1.缓冲区的种类:(缓冲区的作用:http://blog.sina.com.cn/s/blog_5dc7bbf801010fdr.html)
缓冲区 名称 颜色缓冲区 GL_COLOR_BUFFER_BIT //也就是帧缓冲区(FRAME_BUFFER),你需要渲染的场景最终每一个像素都要写入该缓冲区,然后由它在渲染到屏幕上显示 深度缓冲区 GL_DEPTH_BUFFER_BIT //与帧缓冲区对应,用于记录上面每个像素的深度值,通过深度缓冲区,我们可以进行深度测试,从而确定像素的遮挡关系,保证渲染正确。 累积缓冲区 GL_ACCUM_BUFFER_BIT //累积缓存也存储RGBA颜色数据, 将一系列的图像合成一幅图像. 模板缓冲区 GL_STENCIM_BUFFER_BIT //与深度缓冲大小相同,通过设置模版缓冲每个像素的值,我们可以指定在渲染的时候只渲染某些像素,从而可以达到一些特殊的效果
2.glclear()函数的功能:
清除上次显示的结果,每次绘制前都必须调用。
glClearColor(0.0,0.0,0.0,0.0); //将清除颜色设为黑色。(仅仅设置了颜色,并没有用这个颜色去清除任何区域) glClear(GL_COLOR_BUFFER_BIT); //实际完成了把整个窗口清除为黑色的任务。像素检验、裁剪检验、抖动和缓存的写屏蔽都会影响glClear的操作,其中,裁剪范围限制了清除的区域,而glClear命令还会忽略alpha函数、融合函数、逻辑操作、模板、纹理映射和z缓存;
OpenGL 在每一帧开始要调用glClearColor来设置背景色,相当于画布的颜色。必须强调: glClearColor只起到Set的作用,并不Clear任何。
3)glFlush()函数:
保证绘图命令将被执行,而不是存储在缓冲区 中等待其他的OpenGL命令。就是强制刷新。
(OpenGL是使用一条渲染管线线性处理命令的,一般情况下,我们提交给OpenGL的指令并不是马上送到驱动程序里执行的,而是放到一个缓冲区里面,等这个缓冲区满了再一次过发到驱动程序里执行;很多时候只有几条指令是填充不满那个缓冲区的,就是说这些指令根本没有被发送到驱动里,所以我们要调用glFlush来强制把这些指令送到驱动里进行处理。)
4)绘制带有红色背景并且有一个蓝色的矩形的窗体:(测试glClear函数和glClearColor函数)
#include <GL/glut.h> void myDisplay(void) { glClear(GL_COLOR_BUFFER_BIT); //glClearColor(0.0,0.0,1.0,0.0);//重新设置填充色为蓝色,即窗口背景颜色 glColor3f(0.0f, 0.0f, 1.0f);//设置画笔的颜色为蓝色 glRectf(-0.5f,-0.5f,0.5f,0.5f); glFlush(); } int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB); glutInitWindowPosition(600,300); glutInitWindowSize(400,200); glutCreateWindow("我的练习1:红色背景蓝色矩形"); glClearColor(1.0,0.0,0.0,0.0);//设置背景填充色为红色 glutDisplayFunc(&myDisplay);//经过测试,寄存回调过程加不加取地址符都正确。 glutMainLoop(); }