three.js实现烟雾缭绕效果

前端三元同学

共 1754字,需浏览 4分钟

 ·

2021-11-22 23:24

前言

大家好!我是Fly哥,最近接广告的接的有点多, 感谢大家还是一如既往的支持我!respect, 前几天我在朋友圈分享了一个烟雾缭绕的效果。很多小伙伴都表示非常感兴趣,有的同学说用到了噪声, 有的同学说用到了着色器,还有更过分说用到了ps, 胖虎竟然无语凝噎。其实都是就是简单的贴图。配合一点想象力。我们先看下效果:






然后我就发了一条朋友圈,问这个像什么??

有的说 云层, 有的说云墨,有的说雾霭, 其实都不是, 我想做的是烟雾。好的话不不多说!, 本篇文章阅读大概5分钟。不耽误大家太多时间,主要是介绍思路, 说太多也没啥意义。如果你对three.js 还没有一点了解都没有, 都不知道照相机、渲染器、场景等等。你可能会看不懂。你可以先看下这篇文章, 有详细的介绍, 带你入门three.js——从0到1实现一个3d可视化地图。直接去看兄弟们!冲!




粒子动画

我们先仔细分析下这个动画, fly哥最近其实也做了很多动画,谈谈自己的理解其实动画的就是在单位时间内,从一个点变化到另一点,然后每一帧都变化不同的位置、大小、方向, 本质就是多张图片拼接一起,我们都知道fps对吧, 那么这东西到底和requestAnimationFrame() 有啥联系

fps 是什么?

首先介绍一下一些名词的含义

  • 帧:指显示器显示的每一张画面

fps 全称为 Frames Per Second,即 每一秒的帧数。我们在显示器上看到的各种各样的动画效果,都是由一帧一帧组成的。可以将 fps 理解为动画播放的速度。fps 越大,动画越流畅。

一般浏览器的 fps 为 60。当然,如果你的显示器的刷新率能够达到 144 hz 的话,浏览器的 fps 可以达到 144 fps

那什么是刷新率呢?屏幕的刷新率 是指 屏幕每秒能够显示图像的次数,单位为 hz(赫兹)。

fps 的值受限于屏幕的刷新率,即 fps 的值小于等于屏幕刷新率的值

总结:浏览器的 fps 指浏览器每一秒的帧数。fps 越大,每秒的画面就越多,浏览器的显示就越流畅。浏览器的 fps 一般等于屏幕的刷新率,不会超过屏幕的刷新率。

其实就是假设fps 是 60 那么1秒钟同一个物体变化60次,那么其实对于我们人眼来说,肯定是无法发发现的,那么看起来就变成了动画了。其实这就是动画的本质.

缓动函数

什么是缓动函数????

「缓动函数」指定动画效果在执行时的速度,使其看起来更加真实。

现实物体照着一定节奏移动,并不是一开始就移动很快的。当我们打开抽屉时,首先会让它加速,然后慢下来。当某个东西往下掉时,首先是越掉越快,撞到地上后回弹,最终才又碰触地板。

正常可能用到的就是线性变化 linear

image-20211116102519422

其实还有很多种变化有ease... 直接看图:

image-20211116103135329

实现原理:都是使用的cubic-bezier  也就是三阶贝塞尔曲线去做实现的。

生成烟雾粒子

文中的粒子其实都是three.js 中的planeGeometry 然后去贴一个烟雾的贴图, 我先给大家看下贴图:

image-20211116103742049

贴图的话其实就是纹理,然后直接去创建材质,去创建材质去附到plane 上,然后呢 因为是在画布中随机嘛, 然后每一个mesh 的position 都是随机改变的,然后就可以在页面的创建很多烟雾粒子了。

  const smokeMaterial = new THREE.MeshLambertMaterial({
      colornew THREE.Color(0x00dddd),
      map: smokeTexture,
      transparenttrue,
    })
    const smokeGeo = new THREE.PlaneGeometry(width ?? 100, height ?? 100)
    for (let p = 0; p < count; p++) {
      const particle = new THREE.Mesh(smokeGeo, smokeMaterial)
      particle.position.set(Math.random() * 500 - 250Math.random() * 500 - 250Math.random() * 1000 - 100)
      particle.rotation.z = Math.random() * 360
      this.scence.add(particle)
      this.smokeParticles.push(particle)
    }

动画

动画的话其实很简单,就是在每一帧渲染的时候,让每一个粒子的z轴不断去加一个数值,然后就可以实现这样的效果, 因为我这里是线性变化的。你可以加任何缓动函数去修改每一个粒子的位置。

  let sp = this.smokeParticles.length
  while (sp--) {
    this.smokeParticles[sp].rotation.z += 0.002
  }

总结

其实这篇文章我想讲的不是如何去做这个烟雾效果,我想你能够明白,拿到一个动画,你该如何去拆解,去分析,至于那些花里胡哨的效果,我这里可能比较简单,有的动画用到了着色器,其实万变不离其宗哇!掌握本质,没啥做不了的。

源码获得

「关注公众号,私信我,就可以获得本篇文章所有源码」,还是一句话,纸上得来终觉浅,绝知此事要躬行。做和看始终是两种体验,我喜欢喜欢图形的fly,我们下期见!!


浏览 278
点赞
1评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
全部评论
QS774965373ba4a4cc52023-10-24 11:36
大佬,给个资源
点赞回复
推荐
点赞
1评论
收藏
分享

手机扫一扫分享

分享
举报