Chapter6 动画

6.1 双缓冲技术

实际的动画是事先都画好,然后再拿出来显示;但是计算机的动画是画一张就拿出来一张,再画下一张,如果画的图形比较复杂,则可能只画了一半就被观众看到了,这样会导致屏幕的闪烁。

于是可以假设有2张画板,画图的人画好了就与挂在屏幕上的画板交换,这在计算机图形学中被称为双缓冲技术

双缓冲技术:在存储器(很有可能是显存)中开辟两块区域,一块作为发送到显示器的数据,一块作为绘画的区域,在适当的时候交换它们。由于交换两块内存区域实际上只需要交换两个指针,这一方法效率非常高,所以被广泛的采用。

GLUT工具包实现双缓冲:

之前我们写过glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE),其中的GLUT_SINGLE表示单缓冲,如果要使用双缓冲改成GLUT_DOUBLE就行。

同时,还需要交换两个缓冲区,只需要在绘制完成时简单的调用glutSwapBuffers函数就可以了。

glutIdleFunc可以做到在CPU空闲时调用某一函数。

太阳、地球、月亮程序的动画:

#include <GL/glut.h>
// 太阳、地球和月亮
// 假设每个月都是30天
// 一年12个月,共是360天
static int day = 200; // day的变化:从0到359
void myDisplay(void)
{//glEnable(GL_DEPTH_TEST); //启动深度测试(这样后绘制的图形如果在已经存在的图形的前面,它会被遮住,而不是遮住别人glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清空颜色和深度缓冲glMatrixMode(GL_PROJECTION);glLoadIdentity();gluPerspective(75, 1, 10, 400000000);glMatrixMode(GL_MODELVIEW);glLoadIdentity();gluLookAt(0, -200000000, 200000000, 0, 0, 0, 0, 0, 1);// 绘制红色的“太阳”glColor3f(1.0f, 0.0f, 0.0f);glutSolidSphere(69600000, 20, 20);// 绘制蓝色的“地球”glColor3f(0.0f, 0.0f, 1.0f);glRotatef(day / 360.0 * 360.0, 0.0f, 0.0f, -1.0f);glTranslatef(150000000, 0.0f, 0.0f);glutSolidSphere(15945000, 20, 20);// 绘制黄色的“月亮”glColor3f(1.0f, 1.0f, 0.0f);glRotatef(day / 30.0 * 360.0 - day / 360.0 * 360.0, 0.0f, 0.0f, -1.0f);glTranslatef(38000000, 0.0f, 0.0f);glutSolidSphere(4345000, 20, 20);glFlush();glutSwapBuffers();
}void myIdle(void)
{/* 新的函数,在空闲时调用,作用是把日期往后移动一天并重新绘制,达到动画效果 */++day;if (day >= 360)day = 0;myDisplay();
}int main(int argc, char* argv[])
{glutInit(&argc, argv);//对GLUT进行初始化,这个函数必须在其它的GLUT使用之前调用一次glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); //设置显示方式glutInitWindowPosition(100, 100); //设置窗口位置glutInitWindowSize(400, 400);//窗口大小glutCreateWindow("动画"); //根据前面设置的信息创建窗口。参数将被作为窗口的标题。glutDisplayFunc(&myDisplay); //当需要画图时,请调用myDisplay函数glutIdleFunc(&myIdle);glutMainLoop(); //进行一个消息循环return 0;
}

只是在myDisplay的最后加上了交换缓冲区的操作glutSwapBuffers(),然后增加了一个CPU空闲时就执行的函数myIdle,其中调用了myDisplay重新画。

6.2 垂直同步

代码是写好了,但相信大家还有疑问。某些朋友可能在运行时发现,虽然CPU几乎都用上了,但运动速度很快,根本看不清楚,另一些朋友在运行时发现CPU使用率很低,根本就没有把空闲时间完全利用起来。但对于上面那段代码来说,这些现象都是合理的。这里就牵涉到关于垂直同步的问题。

大家知道显示器的刷新率是比较有限的,一般为60-120Hz,也就是一秒钟刷新60-120次。但如果叫计算机绘制一个简单的画面,例如只有一个三角形,则一秒钟可以绘制成千上万次。因此,如果最大限度的利用计算机的处理能力,绘制很多幅画面,但显示器的刷新速度却跟不上,这不仅造成性能的浪费,还可能带来一些负面影响(例如,显示器只刷新到一半时,需要绘制的内容却变化了,由于显示器是逐行刷新的,于是显示器上半部分和下半部分实际上是来自两幅画面)。采用垂直同步技术可以解决这一问题。即,只有在显示器刷新时,才把绘制好的图象传输出去供显示。这样一来,计算机就不必去绘制大量的根本就用不到的图象了。如果显示器的刷新率为85Hz,则计算机一秒钟只需要绘制85幅图象就足够,如果场景足够简单,就会造成比较多的CPU空闲。
几乎所有的显卡都支持“垂直同步”这一功能。
垂直同步也有它的问题。如果刷新频率为60Hz,则在绘制比较简单的场景时,绘制一幅图画需要的时间很段,帧速可以恒定在60FPS(即60帧/秒)。如果场景变得复杂,绘制一幅图画的时间超过了1/60秒,则帧速将急剧下降。
如果绘制一幅图画的时间为1/50,则在第一个1/60秒时,显示器需要刷新了,但由于新的图画没有画好,所以只能显示原来的图画,等到下一个1/60秒时才显示新的图画。于是显示一幅图画实际上用了1/30秒,帧速为30FPS。(如果不采用垂直同步,则帧速应该是50FPS)
如果绘制一幅图画的时间更长,则下降的趋势就是阶梯状的:60FPS,30FPS,20FPS,……(60/1,60/2,60/3,……)
如果每一幅图画的复杂程度是不一致的,且绘制它们需要的时间都在1/60上下。则在1/60时间内画完时,帧速为60FPS,在1/60时间未完成时,帧速为30FPS,这就造成了帧速的跳动。这是很麻烦的事情,需要避免它——要么想办法简化每一画面的绘制时间,要么都延迟一小段时间,以作到统一。

回过头来看前面的问题。如果使用了大量的CPU而且速度很快无法看清,则打开垂直同步可以解决该问题。当然如果你认为垂直同步有这样那样的缺点,也可以关闭它。——至于如何打开和关闭,因操作系统而异了。具体步骤请自己搜索之。

当然,也有其它办法可以控制动画的帧速,或者尽量让动画的速度尽量和帧速无关。不过这里面很多内容都是与操作系统比较紧密的,况且它们跟OpenGL关系也不太大。这里就不做介绍了。

6.3 计算帧速

帧速就是一秒钟内播放的画面数目(FPS)

OpenGL第六讲——动画相关推荐

  1. OpenGL十二讲代码

    文章目录 OpenGL十二讲代码-by yjq 参考资料 第一讲 画一个矩形 第二讲 画一个五角星 画一个圆 画一个正弦函数 第三讲 画点 画虚线 多边形 多边形的两面 前后反转 剔除多边形表面 镂空 ...

  2. 一步一步的使用C++和OPENGL实现COLLADA骨骼动画 第一部分

    一步一步的使用C++和OPENGL实现COLLADA骨骼动画 第一部分   英文原作者:waZim 原文标题:Step by Step Skeletal Animation in C++ and Op ...

  3. NeHe OpenGL第六课:纹理映射

    NeHe OpenGL第六课:纹理映射 纹理映射: 在这一课里,我将教会你如何把纹理映射到立方体的六个面. 学习 texture map 纹理映射(贴图)有很多好处.比方说您想让一颗导弹飞过屏幕.根据 ...

  4. #Apache Spark系列技术直播# 第六讲【 What's New in Apache Spark 2.4? 】

    Apache Spark系列技术直播第六讲 [ What's New in Apache Spark 2.4? ] Abstract(简介): This talk will provide an ov ...

  5. Silverlight Blend动画设计系列六:动画技巧(Animation Techniques)之对象与路径转化、波感特效...

    原文:Silverlight & Blend动画设计系列六:动画技巧(Animation Techniques)之对象与路径转化.波感特效 当我们在进行Silverlight & Bl ...

  6. 趣谈网络协议笔记-二(第十六讲上)

    趣谈网络协议笔记-二(第十六讲上) 流媒体协议:如何在直播里看到美女帅哥? 自勉 给岁月以文明,而不是给文明以岁月!--<三体> 在触不到的獠牙上点火--就像不必仰望那星星就能够解决--就 ...

  7. 趣谈网络协议笔记-二(第六讲)

    趣谈网络协议笔记-二(第六讲) 交换机记忆的到底是端口,还是方向,如果是方向那么何来方向,下图中的感觉更像是网桥? 局域网中的数据是不是必定先经过交换机(网桥,hub)? 为什么广播时mac地址为25 ...

  8. 使用OpenGL实现翻书动画

    2019独角兽企业重金招聘Python工程师标准>>> 上一篇文章介绍了如何通过纹理渲染绘制地球仪,当然OpenGL的三维图形处理能力是很强大的,只要善于利用OpenGL,就能很方便 ...

  9. 第六讲:Obj-C 内存管理4 - 自动释放池

    转:http://tigercat1977.blog.163.com/blog/static/2141561122012111294616203/ 第六讲:Obj-C 内存管理4 - 自动释放池 主要 ...

最新文章

  1. linux-mint 安装 python 包 Gevent
  2. WebQQ hash加密算法PHP版
  3. VMware与KVM全方面对比
  4. java开发C编译器:结构体的解析和执行
  5. 《Python Cookbook 3rd》笔记(4.4):实现迭代器协议
  6. python decimal_python学习笔记一
  7. 【AI视野·今日NLP 自然语言处理论文速览 第一期】Fri, 4 Jun 2021
  8. Myrrix——基于Mahout的开源推荐系统
  9. kubernetes存储详解
  10. aliyun redis 链接超时_超详细的Redis入门指导
  11. 浏览器访问linux终端,使用浏览器访问 Linux 终端
  12. 计算机网络安全综述及防火墙浅析
  13. xshell5免费版本下载
  14. 《算法笔记》胡凡 例题/练习 答案
  15. Linux自学之旅-安装篇(磁盘分区)
  16. 电脑(笔记本/台式)如何关闭UAC
  17. 2020腾讯广告算法大赛赛题复现
  18. c语言寻找完全平方数,菜鸟求助,要怎么求完全平方数?
  19. 基于STM32的ESP8266天气时钟(2)--------MCU获取天气数据
  20. 程序员复工后被裁,600万房21000房贷无力偿还,给年轻人3点忠告

热门文章

  1. 2022第十三届蓝桥杯省赛B组Python
  2. 长沙学院20级训练赛-原魔题解
  3. Cisco路由器IOS升级方法总结
  4. 工作中应该如何管理自己的情绪?
  5. 曾仕强--情绪管理学习笔记--中国人最需要情绪管理
  6. Java中Map集合如何理解(四)——精简
  7. python内置方法+数学模块+随机模块+序列化模块
  8. n-gram的理解与实现
  9. DCMM认证对企业有什么好处?
  10. 从零训练模型:BERT模型【任务:①MLM(掩码语言模型)、②NSP(下一句预测)】