1.引 言 OpenGL是一种相对新的工业标准,它的前身是由SGI公司为其图形工作站开发的IRIS GL,是一个工业标准的三维计算机图形软件接口。 OpenGL不是一种编程语言,而是一种API(Application Programming Interface,应用程序编程接口)。作为一种API,OpenGL库遵循C调用约定,这意味着我们在C语言环境下可以很方便的调用 OpenGL库中的API函数。 Microsoft开始把 OpenGL集成到Windows NT中,后来又把它集成到新版本的Windows 95 OEM Service Release 2中,用户既可以在 Windows 95、Windows NT环境下开发OpenGL应用程序,又可以很方便的把已有的工作站上的程序移植过来。 2.双缓冲技术 这项技术能使你执行绘图代码时能够在一个屏幕之外的缓冲区内进行渲染,然后用交换命令把图形放到屏幕上。双缓冲技术有两种用途,第一个是有些复杂的图形可能要花很长的时间绘制,而你又不希望图像绘制的所有步骤都被看见,使用双缓冲技术就可以合成一幅图像并在完成后才显示出来。用户永远不会看到不完整的图像,只有整幅图像准备就绪之后才会把它在瞬间置于屏幕之上。双缓冲技术的第二个用处是制作动画。每一帧都在画面外的缓冲区绘制,完成之后再交换到屏幕上。 OpenGL支持双缓冲,但是并不是真正用来交换前台缓冲区和后台缓冲区的。 实际上,每个OpenGL支持的窗口系统都可以通过一个函数调用来实现前后缓冲区之间的交换。 ★ 在Windows编程环境下调用下面函数: SwapBuffers(dc); ★ 在C语言编程环境下调用下面函数: glutSwapBuffers(); 3.在C语言编程环境下如何实现动画 在C语言编程机制下实现OpenGL动画,主要是通过调用OpenGL API函数库来实现,以下便是具体的实现代码框架。 ……… ………//#include调用,及变量声明,相关函数声明和函数定义。 // 主函数入口 void main(void) { glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); //指定一个双缓冲窗口,这使得所有绘图代码都在画面外缓冲区进行渲染。 glutCreateWindow("NAME"); glutDisplayFunc(RenderScene);//调用RenderScene函数绘制当前窗口 ………… glutTimerFunc(33, TimerFunction, 1);//登记一个回调函数,经过设定的时间值后由GLUT调用该函数。 ………… glutMainLoop();//这个函数开始主GLUT事件处理循环。 } //主函数中所调用的函数定义 ……… void RenderScene(void) { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除颜和深度缓冲区。 glColor3ub(255,0,0);//设置当前颜色为红色。 glPushMatrix();//将当前矩阵压入堆栈 glRotatef(dIst, 1.0f, 1.0f, 3.0f); //所画物体绕经过(0,0,0),(1,1,3)的矢量逆时针旋转dIst的角度。 glTranslatef(10.0f,0.0f, 0.0f);//将所化物体沿X轴平移10个单位。 glutSolidSphere(8.0f, 15, 15);//画一个实心圆。 glPopMatrix();//弹出先前所压矩阵 dIst += 10.0f; if(dIst > 360.0f) dIst = 0.0f; glutSwapBuffers();//在双缓冲模式下进行一次缓冲区交换。 } ……… void TimerFunction (int value) { glutPostRedisplay();//刷新当前窗口 glutTimerFunc(33, TimerFunc, 1); } 上述相关代码主要完成了在屏幕上绘制一个绕经过(0,0,0),(1,1,3)的矢量逆时针旋转的小球。每隔33毫秒刷新一次。 具体运行结果如图1所示: 图1. C语言环境下滚动的小球
4.在Windows编程环境下如何实现动画 在Windows编程模型中,实现动画的方法有很多种,这里我们只介绍一种很常用的方法。 ★ 计时器实现动画的方法 在Windows编程模型中,用计时器方法来实现动画是很方便的。在编程环境下创建一个计时器,该计时器通知Windows想让WM_TIMER消息隔多长时间给你的窗口发送信息。Windows通过响应这个消息,就能够以一定的时间间隔完成你所要完成的任务。 LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { ……… ………//声明变量 switch (message)// Windows的消息处理 { case WM_CREATE: { hDC = GetDC(hWnd); //得到窗口的句柄。 SetDCPixelFormat(hDC);//设置像素格式。 ……… SetTimer(hWnd,101,33,NULL);//该函数创建一个有指定超时值的计时器。} break; case WM_DESTROY: { KillTimer(hWnd,101);//删除计时器。 ………} break; case WM_TIMER: {……… InvalidateRect(hWnd,NULL,FALSE);} break; /*处理计时器事件时,设置一个情况语句用来处理WM_TIMER消息,在该消息处理语句中,我们可以实现OpenGL中所要求的渲染,贴图等,也可以产生连续更新的图像,这也是我们所要求的动画。当然,我们在该消息处理语句中,也可以不加入上述代码,只是简单的加入使应用程序窗口无效的语句,而具体的渲染或动画产生代码则可以加入WM_PAINT消息处理程序中。*/ case WM_PAINT: { ……… RenderScene();//该函数产生动画。 SwapBuffers(hDC);// 缓冲区交换。 ……… ValidateRect(hWnd,NULL);//使窗口生效。 } break; default: // Passes it on if unproccessed return (DefWindowProc(hWnd, message, wParam, lParam));//确保每一个消息都得到处理。 } return (0L); } ……… void RenderScene() { //加入相应的动画实现代码 } ……… 具体实现结果如图2所示 /*在上述代码中,我们可以看见在WM_PAINT消息处理程序中有ValidateRect语句,该语句使窗口生效。如果我们省略该函数,那么Windows操作系统认为窗口总处于刷新的状态,并且会时刻将WM_PAINT消息流发送给应用程序。这样我们可以看见动画的帧速率增加了很多。*/ 具体运行结果如图2所示:
图2. Windows编程环境下滚动的小方块 5.小结 综上所述,我们详细介绍了OpenGL动画的生成原理,以及如何在两种编程环境下实现动画的具体代码。在C语言编程机制下,我们主要使用GLUT库函数来实现动画,具体的相关函数的应用我们可以参考OpenGL库函数。 在Windows编程机制下,读者应该具有Windows入门级编程的基本知识,而且你也应该对Windows API 函数库有相当的了解,这样你才会熟练掌握该方法。正如以前所说,在该机制下我们有多种实现动画的方法,比如:事件插入循环,使用渲染线程等等。这里我们就不做一一介绍,具体的实现框架与上述方法类似。 双缓冲技术对于在任何一种机制下实现动画都是必要而且有效的。 |