近年来,随着互联网的迅速发展,用户对产品的视觉效果需求也更加强烈。生动逼真的3D动画效果可以让用户身临其境,叹为观止。
从上面的动图可以看到
下面我会介绍一下如何一步步实现这种粒子系统效果。
在web端实现3D效果时,第一个相到的当然都会是webGL(webgraphiclanguage),即浏览器原生的一套图形API,但是使用webGL进行复杂3D效果的开发会大大增加工作量,比如坐标变换,法线贴图、透视模拟等等。所以three应运而生,官方对其的介绍是A3Djavascriptlibrary,早期是由计算机图形学天才RicardoCabello在2010年开源的框架,至今已有10年的历史。在three世界的三大概念分别是camera(相机),scene(场景),renderer(渲染器),下图是三者的对应关系。
场景我们可以理解为一个舞台,一个程序只能同时有一个场景。
对应现实世界当中的照相机,我们在屏幕中所看到的所有图像都是由相机来捕捉到的。three提供的相机有三种,分别是PerspectiveCamera(透视相机)、OrthographicCamera(正交相机)以及CubeCamera(立方体相机)。
创建一个透视相机:
fov:视场角,是显示边缘与摄像机连线的夹角,游戏中通常为40-60,这里取值50;
aspect:渲染结果横向尺寸和纵向尺寸的比值,推荐默认值为窗口的长宽比;
near:从距离摄像机多近的位置才开始渲染,推荐默认值0.1;
这样一个场景就搭建好了,我们先在场景中添加一个最简单的物体,点(point)。
通常一个物体是由材质(material)和形状(geometry)组成的,材质定义了物体的外观,形状则定义了物体的结构。在创建材质的时候可以选取一张纹理贴图(texture)去充当材质,这里加载一张的球形展开图。
一个点也可以理解为一个粒子,其中vertices是粒子的位置,它是一个只存储XYZ坐标的32位浮点类型数组,我们可以传入尽量多的粒子来充满屏幕。
然后将点添加到场景中,这样就在屏幕前渲染了一万个随机位置的粒子。
最开始看到的粒子LOGO的实现原理是将一个3D模型的顶点(vertices)一一对应到生成的粒子坐标中,可以理解为加载模型的目的是获取到粒子的坐标和数量。所以生成粒子的LOGO的步骤如下:
最终实现了模型到粒子的效果
这样只需要提供一个3D模型就可以渲染出对应的粒子轮廓,下面我们让粒子动起来吧。
我们获取到了模型中的所有顶点坐标,并且可以生成随机的点,如何将随机的点逐渐汇聚成一个模型呢,这里要应用到Tween动画的技术。
下图分别为线性函数表达式式、函数、js代码
下面是一些使用Tween动画技术处理后的效果
到这里我们就完成了模型到粒子的所有工作,并且让粒子可以在模型之间互相切换,但是单纯从效果看来还是有一些生硬。就像没处理过的电影原片,在电影行业里拍摄完画面需要加上一些特效或者调色,称之为后期处理,下面我们来对粒子的效果做一些后期处理。
辉光是一种现实世界中的光现象,通过它能够以较为适度的渲染性能成本极大地增加渲染图像的真实感。在现实世界中,辉光是由于光线在大气或我们眼睛中产生散射而造成的。我们用肉眼观察黑暗背景下非常明亮的物体时会看到辉光效果,比如夜晚的路灯,车灯和屋外的窗户等,它们提供了亮度和气氛的强烈视觉信息。然而通常我们的屏幕不支持HDR(高动态范围),无法渲染太亮的物体。于是我们模拟了当光线射到胶片或摄像机前时眼睛中出现的效果。辉光处理给屏幕上显示的LDR(低动态范围)图像添加真实感。
辉光作用前后对比
可以看到最终形成的模型的点位置还是有些太规整了,我们想让他呈现出一些不规则的毛边效果,但是整体上还是能保证轮廓的,我们先使用在每个点的位置加上一个随机数的offset来改变坐标,把它命名为白噪声。
白噪声带来效果虽然每个点的位置的能够和原始位置保证差异,但是模型整体上会显得杂乱无章。
在1982年的《电子世界争霸战争》中,图形学专家KenPerlin首次提出柏林噪声(Perlinnoise)算法的概念,并应用到了电影中的地形处理,模拟出了高低起伏的地形。(并因此获得了奥斯卡最佳技术成就奖)
柏林噪声的实现有以下三个步骤:
1.定义一个晶格结构,每个晶格的顶点有一个“伪随机”的梯度向量。对于二维的柏林噪声来说,晶格结构就是一个平面网格,三维的就是一个立方体网格。
2.输入一个n维向量,我们找到和它相邻的2个晶格顶点,计算该点到各个晶格顶点的距离向量,再分别与顶点上的梯度向量做点乘,得到2个点乘结果。
3.使用缓和曲线来计算它们的权重和。在原始的柏林噪声实现中,缓和曲线是s(t)=3t22t3,在2002年时Perlin本人将其改进为s(t)=6t15t+10t3。如果直接使用的线性插值的话,它的一阶导在晶格顶点处(即t=0或t=1)不为0,会造成明显的不连续性。s(t)=3t22t3在一阶导满足连续性,s(t)=6t15t+10t3在二阶导上仍然满足连续性。
使用噪声的算法对模型的顶点位置和颜色进行处理后
运动可以赋予整个场景生命力,我们可以将粒子进行沿Z轴的循环运动,让整个模型呼吸起来。这里只让随机20%的粒子进行运动,剩下的粒子保持静止。