3D动画
1.使用requestAnimationFrame()来驱动动画
从前,Web应用使用定时器(timer)来控制页面内容动画,通过setTimeout()或setInterval()这两个函数。随着Web
应用开始包含更复杂的动画和交互,这种方式明显遭遇到一些关键问题。
1).定时器也设置好的恒定间隔来调用函数,无论是否是绘制图形的最佳时机。
2).在定时器回调中执行的Javascript代码无法与其他浏览器计算产生的动画时间轴同步。
3).无论页面或者标签是否可见,或浏览器窗口是否被最小化,定时器都会被重复执行,这会造成潜在的绘图资源浪费。
4).Javascript应用代码不知道显示器的刷新率,所以只能主观地设定定时器间值。例如将其设置为1/24秒,那么使用60Hz刷新率的用户将无法感受到流畅的视觉效果。
requestAnimationFrame()函数被设计用来解决以上问题。使用它的好处。
第一,浏览器可以按照所需进行频繁或不频繁的调用。当浏览器还有足够的空闲时间时,它可以试着提高帧频来赶上显示器的刷新率。相反,如果页面或页签隐藏了,或整个浏览器最小化了,它可以减少回调函数执行次数,优化电脑或设备的资源使用。第二,浏览器可以批量处理用户绘图操作,从而减少绘制屏幕的次数,节省资源。第三,在requestAnimationFrame()中执行的所有绘制代码最终会与其他绘图操作进行合并。最终产生更平滑、更快速、更高效的页面绘制以及动画。
2.创建3D动画的几种方式
1).使用程序更新属性的方式来构建动画。
2).使用补间来进行动画过度。
3).使用关键帧来实现复杂动画。
4).使用曲线和路径创建平滑自然的运动。
5).使用变形目标来创建人物和面部动画。
6).使用蒙皮来构建角色动画。
7).使用着色器来进行动画。
3.使用程序更新属性的方式构建动画
在WebGL场景中启动一个动画最简单的方式是编写代码,在运行循环每次执行的时候更新某个物体的属性值。这个概念可以延伸到给场景中的任意东西添加动画:位置、旋转、缩放、材质颜色、透明度,等等。通过使用Javascript代码来更新熟悉,我们可以进行任意的计算更新。数学公式、布尔逻辑、统计值、数据流、实时传感器输入等都可以用来驱动动画。
4.使用补间来进行动画过度
补间指的是计算一对值中间插入的其他数值的过程。有了补间,动画绘制者值需提供动画的起始值和结束值,用于动画时间过程中的中间值(补间)有引擎自动计算生成。补间是实现由一个状态切换到另一个状态的一次性简单动画的完美选择,如点击鼠标移动一个物体。
补间通过一项被称为插值(interpolation)的数学技术来实现。插值指的是基于一个标量输入(如时间或者分数值)来计算两个值之间的一个值。
自动实现简单的补间是非常容易的事。尽管如此,当你需要非线性的插值函数,或者其他像淡入/淡出这类花哨的效果时,问题就变得复杂了。你需要一个现成的库,而非构建自己的补间体系。Tween.js是一个流行的开源补间通用库。它被用于许多流行的WebGL工程中。
5.使用关键帧来实现复杂动画
补间非常适用于来创建简单的过度效果。更复杂的动画通过使用关键帧,将补间的概念上升了一个层次。关键帧动画包括一系列的值,以及可能各部相同的值与值之间的间隔时间,而非指定一对单值来进行补间。关键帧数据由两部分组成:一个时间(键)列表和一个值列表。值列表表示在相应键的时间点会被使用的属性值; 动画系统基于一对键之间的间隔事件值计算补间。
尽管补间和关键帧动画都采用插值,但它们之间存在两个主要的不同点:关键帧动画可以包含两个以上的值,不同关键帧之间的时间间隔可以不同。这使得更强大的效果得以实现。下面是一个关键帧配置示例:
lightAnimator = new KF.KeyFrameAnimator; lightAnimator.init({ interps: [ { keys:[0, .4, .6, .7, .8, 1], values:[ { r: 1, g : 1, b: 1 }, { r: 1, g : 1, b: 1 }, { r: .333, g : .333, b: .333 }, { r: 1, g : 1, b: 1 }, { r: .667, g : .667, b: .667 }, { r: 1, g : 1, b: 1 }, ], target:directionalLight.color }, ], loop: loopAnimation, duration:duration * 1000, }); lightAnimator.start();
6.使用曲线和路径创建平滑自然的运动
关键帧数据不局限于用来描述线性动画。它也可以被看作曲线上的一些点。动画中最常用的曲线是样条曲线(spline-curve)---一种光滑连续的曲线。被称为B样条曲线的某类样条曲线被广泛应用于计算机图形中,因为他们可以相对快速地被计算出来。
7.使用变形目标来创建人物和面部动画
关键帧和关节动画非常适用于在场景中移动物体,但许多动画还需要该案物体本身的集合形状。用于实现这类效果的最常用方法是变形目标动画(morph target animation),简称变形。变形使用基于顶点的插值来改变网格的顶点。通常,网格顶点的一个子集以及US噢因一起,被当做即将用于在补间中的变形目标(morph target)存储起来。变形目标各顶点值之间的插值,以及使用了这些插值的动画,组成了网格顶点的变形。
变形不仅仅可以用于表现面部。Three.js工程目录中的一些示例使用变形来构建整个角色的动画。MD2格式是一个流行的基于变形的格式,它被用于游戏中的玩家角色动画。
8.使用蒙皮来构建角色动画
关节动画在表现无生命物体时非常出色,想机器人、汽车、机器,等等。但在表现邮寄运动的时候则并不理想。微风中摇曳的植物,蹦蹦跳跳的动物,以及跳舞的人们,所有这些都涉及网格的几何形状变化:肢体的流动,皮肤的延展。你几乎不可能用关节动画的模式来很好地模拟这些事务。因此我们转向另一项被称为蒙皮动画(skinned animation, skinning)的技术,这项技术有被称为骨骼动画(skeletal animation),或但网格动画(single mesh animation)。
蒙皮动画涉及对网格(或者说,蒙皮)上的的当前顶点进行实时变换。动画由一个呗称为骨骼的关节物体成绩结构来驱动。骨骼仅仅被用作动画的皮下机制,我们不会再屏幕上看到它。
骨骼中的每根骨头都和网格上的一个顶点集合以及每个相关顶点的融合权重(blend weight,又称顶点权重,vertex weight)相关联。
9.使用着色器来进行动画
关键帧、补间和蒙皮,都是可以用Javascript来实现的,不过你也可以使用GLSL可编程着色器来实现硬件加速的版本。Three.js中的动画同时使用两种策略:纯Javascript的关键帧系统,以及作为Three.js内置材质(如Phong 和 Lambert)的着色器代码的一部分而实现的变形和蒙皮。