header_v0.7.2

3D粒子效果在网页端实现分享

83天前发布

原创文章 / UI / 教程
腾讯游戏TGideas 原创,如需商业用途或转载请与腾讯游戏TGideas联系,谢谢配合。

3D粒子效果在网页端实现分享。

线上地址


在UP 2017预热站中,页面使用了粒子效果,点击 UP2017预热站 先看一下效果

 

14ac590ae161a8012145504fd975.jpg

30秒快问快答


Q:这个H5用到了什么技术?背景是视频吗?
A:首先,这个其实是个PC站点,最初也没有计划在手机上浏览。背景不是视频,是WebGL,实现上用的是包装好的three.js库


Q:模型是怎么做的?
A:和普通的3D建模一样,常规的3D建模软件即可;然后使用插件导出为three.js可方便读取的JSON格式


Q:花了多久时间?
A:这个项目设计和前端是从2月底开始的,然后4月初页面基本完成。期间包括了前期的技术预研、可行性评估等;和我平时遇到的项目不同的是,这次的设计和前端两者是同步进行的。

 

流程总览


今年UP2017主题为 奇点·共生,如果使用粒子效果来营造效果,会非常契合主题!于是就有了下文。


我花了10天左右的时间,弄出来一个初始的Demo,实现了粒子的展现、变换。和大家讨论了下,觉得效果不错,于是便继续沿着这个方向下去。


设计和前端同步进行:3D建模然后转换格式,再导入页面,并使用JS控制动画、交互。

 

因为涉及的点会比较多,所以我决定从各个小的板块来分开说明,可能会比较散。对于有兴趣继续了解的前端开发er,建议先跑一遍three.js的quick start,网上搜一下应该会比较多的。


模型


使用常规的3D建模软件即可。下面的左图是线框视图,右图是页面效果。


模型的要求,具体到这次的项目来说,需要顶点均匀分布;如果需要一些图案,是通过点的密集程度来体现的。

然后给到我的是3D模型,给到我再处理。我这次使用的是Blender,尝试过几次,兼容性比较好的是fbx格式,然后通过给Blender安装插件之后,将模型转换为便于three.js读取的JSON格式。


导入过程参考文章:Importing a Modeled Mesh From Blender to Three.js


由于这次只需要顶点信息,参考下图的参数设置导出即可。


b018590ae195a801214550bd470c.jpg


然后得到模型的JSON格式的数据,在页面中加载并读取它,这里使用的加载器是THREE.JSONLoader


如果只希望显示顶点,比如这次的项目,用THREE.js建立3D物体的时候它有专门的粒子系统:Points,以及与之对应的材质PointsMaterial


动画


页面动画主要有切换动画、KV的动画以及二维码的动画,下面会分别说明。THREE.js负责将图形显示出来,粒子间过渡时候的缓动动画使用的是tween.js来控制。


切换动画


只是把模型显示出来还是相对简单的,使用THREE.Points载入顶点几何体和PointsMaterial材质即可,主要难点是切换的动画。因为各个模型的顶点数是不同的,如果要切换,不能一一映射。


每天想着这个问题,某天突然就灵光一现了,我可以先读取所有的模型的顶点信息,然后得到所有的模型中顶点数最多的一个的顶点数量,新建一个拥有这么多个顶点的Points作为全场的动画承载体,其余的模型只是用来记录顶点位置,不直接参与表演。


这样一来,模型的切换动画就简单多了。你可能要问,多余的点怎么办,飞到屏幕外吗?其实不用,多余的点从头开始就好了。


比如说承载体有10000个粒子,对于一个有9000个顶点的模型,多余的1000个顶点继续从头开始。9001到10000间的点和1到9000间的点重叠在一起即可。


最初的时候发现动画有些生硬,但是一直想不通为什么,后来突然明白了,因为所有粒子“齐步走”,于是改进了下,利用了tween.js的delay方法:


tween.delay(animationDuration*Math.random());

 

齐步走的粒子们 vs 随机延迟起步的粒子们:


e91e590ae1bea8012145504a7c50.jpg



加上了随机的延迟之后的效果,自然多了。


最后一页的KV动画


93d1590ae1e2a80121455003f0e4.jpg


KV的动画是裙边的效果,具体的表现就是,它有一个中心,离这个中心越远的地方,振幅越大。然后,又是周期平滑运动,正弦函数就是这种情况使用的啦,组装了一下,如下图的公式。


f20a590ae209a801214550eeeff5.jpg


实际使用的时候,可能要加一些系数微调一下,比如用sine里面的部分控制周期、外面乘以的系数可以控制振幅。


二维码动画


另外页面有一个不太起眼的小角落,右下角藏着一个二维码哟。


6749590ae220a80121455060c525.jpg

这个二维码其实也是一个三维的模型,切换方面的原理和之前的几何体一样,唯一的差别是材质不同。几何体是圆形的点,二维码的材质是方块形,材质的map设置为null即可是方形啦(没有纹理默认方形)


new THREE.PointsMaterial({
...
map: null, //texture
...});


氛围


氛围是什么?其实就是后期处理(postprcess),一图胜千言:


d7f9590ae23fa801214550bfe636.jpg


左图是处理前的,相对比较生硬。右图主要使用了fog和composer (三方插件)


fog好理解,和现实中的雾/霾类似,设定一个距离,在这个范围内可见,超过之后就慢慢消失在“浓雾”里了

scene.fog = new THREE.FogExp2(0x05050c, 0.0005);renderer.setClearColor(scene.fog.color);


三方的composer很多,这里用的是alteredq的一系列EffectComposer,包括过亮效果、暗角、电视效果等。

还有就是页面上一些悬浮的小颗粒,这个是用了3个粒子系统,然后错落着运动实现。


优化


切换的时候有点卡,后来发现是初始化tween实例造成的(怎么发现的?因为我发现不初始化tween就不卡了),所以这里就把tween示例放到了每一个顶点对象上,有则复用无则初始。切换过程流畅度大大提升了。


if(!vtx.tweenvtx){
vtx.tweenvtx=new TWEEN.Tween(ele)
...};


剩下的优化点主要就是移动端了。


移动端的体验不是很好的,不过尽量优化下。首先想到的是粒子数减少一些,使用了SimplifyModifier这个修改器(Modifier),画面是有部分损失的,但是流畅度提升了不少,但是在安卓上有个问题,它的计算过程特别慢,具体算法不知,可能是不支持部分特性导致的吧。然后就没有采用这个方法了。


既然不能减,那至少不增加。在最后一个KV上,其实是使用了一个TessellateModifier的,Tessellation是细分曲面,常玩单机游戏的同学可能在画质设定里面看到过这个单词。也就是在顶点与顶点之间自动嵌入新的顶点。画面对比,右侧是动态增加顶点的效果:


e8eb590ae25da801214550a0df8f.jpg


最后,分辨率,移动端本来按照习惯是要根据屏幕的devicePixelRatio来设定分辨率的


renderer.setPixelRatio(window.devicePixelRatio);


但是为了流畅度,这里舍弃了


上线


跨域的问题


原本计划周一上线,但是周五快下班的时候,遇到这个问题,很焦急。搜了一圈,在TextureLoader里面找到个选项,不为null即可,是的,即使是空字符串也OK


var loader = new THREE.TextureLoader();loader.crossOrigin='';


流畅度方面,如万技师大神所言,使用vertex shader性能可能更好,感觉好高深,有时间可以继续研究下。


by Bobs cript

317

    文章信息

    意见反馈
    没有新消息

    提示文案

    提示文案

    提示失败
    提示成功