1.7 动画

来源:互联网 发布:淘宝小号怎么注册 编辑:程序博客网 时间:2024/05/28 01:34

动画是由一副一副静止的画面组成的,通过在静止画面之间快速切换,比如1秒钟切换24副画面,而这24副画面之间的差别较小,这样我们的大脑会将前一副画面和后一副画面连接起来,形成平滑的动画。小时候的连环画,就有点动画的意思了,快速翻看连环画,就看到画面仿佛动起来了。


双缓冲

由于计算机程序没有那么多的纸张来描画静止画面,它只有一个显示屏,所以就导致两幅画面切换之前,需要擦除原来的画面,然后画上新的画面。这就导致一个问题,前一副画面只擦除了一半,然后后一副画面描画了一半,这样的情况是会出现的。这样的情况,通常会导致屏幕的闪烁。为了防止这种现象,就出现了双缓冲这个概念。
双缓冲,其实就是两个颜色 缓冲区,一个用来显示前一个画面,一个用来绘制后一个画面。假设有A,B,C三个画面,做成连环画。两个缓冲区,分别叫M和N好了。最开始的时候,在M缓冲区显示A画面,然后在N缓冲区,绘制B画面,当B画面绘制完毕后,交换M和N缓冲区,这时N缓冲区在前,M在后。接着在M缓冲区继续绘制C画面,当C画面绘制完毕后,又交换两个缓冲区。这样,每次看到的都是绘制完毕的画面了,这样就不会看到不完整的画面了。
                       
最终结果如第二张图所示。当然,缓冲区M,N的名称是不会显示在图像中的,我们看到的最终就是 空图像->A->B->C。

暂停刷新

这个小节指的是每帧的绘制时间, 与视频刷新时间 不一致的时候,会出现什么样的情况。
每帧的绘制时间:每帧,就是指每一个静止的图像。要画一幅静止的图像,需要时间,每帧绘制时间,指的就是这个时间。
视频刷新时间: 每帧绘制完毕后,图像是放在缓冲区中,并没有真实显示出来。要显示出来,就需要由视频进行刷新。视频的刷新时间,是指视频将屏幕上的所有像素,刷新一次,需要的时间。视频的刷新时间,通常由视频刷新频率给出。

1. 每帧的绘制时间 < 视频刷新时间。 也就是说,缓冲区中的内容已经准备好了,视频还在刷新上一帧的数据。这其实可以接受,因为下一次视频刷新时,可以从缓冲区中取数据。
2. 每帧的绘制时间 > 视频刷新时间。 也就是说,我视频上一帧已经刷新完毕了,而缓冲区还没为我准备好下一帧的数据。这样视频刷新处于等待状态。这样的结果就是错过了视频刷新时间,只能等到下一次进行视频刷新了,这样画面就显得有点卡了。
3. 每帧的绘制时间 = 视频刷新时间。 按理说,这样的情况是最好的,谁也没等谁,两者同步了。但是,由于视频刷新时间是固定的,而每帧的绘制时间会有一些偏差。这样就会导致帧率的不稳定。帧率是指单位时间内的视频帧数。这样产生的效果就是,如果以一个人走路来打比方,就是走得时快时慢,并不匀速。

动画=重绘+交换

没什么可讲的了,直接看例子。
这个例子使用了双缓冲,使用双缓冲,有两处需要注意,一是main函数中的glutInitDisplayMode的参数,二是display函数末尾的glutSwapBuffers。
然后这个函数其他就是正常的绘制正方形。
只是多了一个正方形的旋转角度。spin这个角度在spinDisplay函数中增加,在display函数中使用。而spinDisplay函数,又是在mouse函数中指定为空闲函数。按下鼠标左键,当程序空闲时,就会调用spinDisplay,这个函数内部增加了spin的值,然后通过调用glutPostRedisplay函数,又让程序去调用display函数。这样,下一帧的正方形,就在上一帧的基础上,旋转了2度。只是现在的计算机足够快了,看起来这个正方形的旋转并不连贯。
#include <GL/glut.h>#include <stdlib.h>static GLfloat spin = 0.0;//正方形的旋转角度void display(void){glClear(GL_COLOR_BUFFER_BIT);//清除背景glPushMatrix();//模型视图矩阵 入栈glRotatef(spin, 0.0, 0.0, 1.0);//指定模型绕Z轴旋转,Z轴指向屏幕外面glColor3f(1.0, 1.0, 1.0);//白色矩形glRectf(-25.0, -25.0, 25.0, 25.0);//矩形glPopMatrix();//模型视图矩阵出栈glutSwapBuffers();//交换缓冲区}void spinDisplay(void){spin = spin + 2.0;//旋转角+2度if (spin > 360.0)spin = spin - 360.0;//避免旋转角超过360度glutPostRedisplay();//重新绘制,这导致display函数被调用}void init(void){glClearColor(0.0, 0.0, 0.0, 0.0);//背景清除颜色为黑色glShadeModel(GL_FLAT);//使用单色绘制物体}void reshape(int w, int h){glViewport(0, 0, (GLsizei)w, (GLsizei)h);//指定视口大小glMatrixMode(GL_PROJECTION);//进入投影矩阵glLoadIdentity();//投影矩阵设置为单位矩阵glOrtho(-50.0, 50.0, -50.0, 50.0, -1.0, 1.0);//指定裁剪空间glMatrixMode(GL_MODELVIEW);//返回模型视图矩阵glLoadIdentity();//模型视图矩阵设置为单位矩阵}void mouse(int button, int state, int x, int y){switch (button) {case GLUT_LEFT_BUTTON:if (state == GLUT_DOWN)glutIdleFunc(spinDisplay);//鼠标左键按下时,设置空闲函数为spinDisplaybreak;//每当程序空闲时,就会调用spinDisplay函数case GLUT_MIDDLE_BUTTON:if (state == GLUT_DOWN)glutIdleFunc(NULL);//鼠标中键按下时,设置空闲函数为空,空闲时不做任何事break;default:break;}}/**  Request double buffer display mode.*  Register mouse input callback functions*/int main(int argc, char** argv){glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);//使用双缓冲模式,使用RGB颜色模式glutInitWindowSize(250, 250);//指定窗口大小glutInitWindowPosition(100, 100);//窗口初始位置glutCreateWindow(argv[0]);//创建窗口init();//初始化glutDisplayFunc(display);//指定显示函数glutReshapeFunc(reshape);//指定窗口尺寸变化时的函数glutMouseFunc(mouse);//指定鼠标事件对应的处理函数glutMainLoop();//进入消息循环return 0;   /* ANSI C requires main to return int. */}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 足球鞋买大了怎么办? 军靴穿着磨脚怎么办 军靴磨大脚趾怎么办 想开服装店没经验怎么办 我鼻子大怎么办啊 副局长不听局长的话怎么办 边防改制部局怎么办 毛中老师打人怎么办 老婆是个泼妇怎么办 一年级孩子学习不好怎么办 生活作息不规律怎么办 作息时间不规律怎么办 能醒不想起床怎么办 不想起床怎么办 神回复 孩子不起床上学怎么办 孕晚期起床困难怎么办 腰间盘疼痛起床困难怎么办 小学生做作业拖拉怎么办 被手机贷起诉怎么办 大人睡颠倒了怎么办 熬夜长斑了怎么办 ps遇到文件尾怎么办 pdf用ps打不开怎么办 ps安装不上怎么办 工作原因经常熬夜怎么办 熬夜皮肤暗黄怎么办 经常熬夜睡眠不好怎么办 经常熬夜皮肤不好怎么办 皮肤熬夜变暗黄怎么办 晚上上夜班白天睡不着怎么办 熬夜肾虚怎么办才能好 经常熬夜口气重怎么办 晚上睡不着白天起不来怎么办 晚上熬夜白天睡不着怎么办 在外打工孩子上学怎么办 婴儿脸干燥发红怎么办 宝宝脸上红点点怎么办 药流出血量少怎么办 药流喝药第一天发烧了怎么办 药流第一天量很少怎么办 小孩不想吃饭口臭怎么办