three.js實(shí)現(xiàn)煙霧繚繞效果
前言
大家好!我是Fly哥,最近接廣告的接的有點(diǎn)多, 感謝大家還是一如既往的支持我!respect, 前幾天我在朋友圈分享了一個(gè)煙霧繚繞的效果。很多小伙伴都表示非常感興趣,有的同學(xué)說(shuō)用到了噪聲, 有的同學(xué)說(shuō)用到了著色器,還有更過(guò)分說(shuō)用到了ps, 胖虎竟然無(wú)語(yǔ)凝噎。其實(shí)都是就是簡(jiǎn)單的貼圖。配合一點(diǎn)想象力。我們先看下效果:
然后我就發(fā)了一條朋友圈,問(wèn)這個(gè)像什么??
有的說(shuō) 云層, 有的說(shuō)云墨,有的說(shuō)霧靄, 其實(shí)都不是, 我想做的是煙霧。好的話不不多說(shuō)!, 本篇文章閱讀大概5分鐘。不耽誤大家太多時(shí)間,主要是介紹思路, 說(shuō)太多也沒(méi)啥意義。如果你對(duì)three.js 還沒(méi)有一點(diǎn)了解都沒(méi)有, 都不知道照相機(jī)、渲染器、場(chǎng)景等等。你可能會(huì)看不懂。你可以先看下這篇文章, 有詳細(xì)的介紹, 帶你入門(mén)three.js——從0到1實(shí)現(xiàn)一個(gè)3d可視化地圖。直接去看兄弟們!沖!

粒子動(dòng)畫(huà)
我們先仔細(xì)分析下這個(gè)動(dòng)畫(huà), fly哥最近其實(shí)也做了很多動(dòng)畫(huà),談?wù)勛约旱睦斫馄鋵?shí)動(dòng)畫(huà)的就是在單位時(shí)間內(nèi),從一個(gè)點(diǎn)變化到另一點(diǎn),然后每一幀都變化不同的位置、大小、方向, 本質(zhì)就是多張圖片拼接一起,我們都知道fps對(duì)吧, 那么這東西到底和requestAnimationFrame() 有啥聯(lián)系
fps 是什么?
首先介紹一下一些名詞的含義
幀:指顯示器顯示的每一張畫(huà)面
fps 全稱(chēng)為 Frames Per Second,即 每一秒的幀數(shù)。我們?cè)陲@示器上看到的各種各樣的動(dòng)畫(huà)效果,都是由一幀一幀組成的??梢詫?fps 理解為動(dòng)畫(huà)播放的速度。fps 越大,動(dòng)畫(huà)越流暢。
一般瀏覽器的 fps 為 60。當(dāng)然,如果你的顯示器的刷新率能夠達(dá)到 144 hz 的話,瀏覽器的 fps 可以達(dá)到 144 fps
那什么是刷新率呢?屏幕的刷新率 是指 屏幕每秒能夠顯示圖像的次數(shù),單位為 hz(赫茲)。
fps 的值受限于屏幕的刷新率,即 fps 的值小于等于屏幕刷新率的值。
總結(jié):瀏覽器的 fps 指瀏覽器每一秒的幀數(shù)。fps 越大,每秒的畫(huà)面就越多,瀏覽器的顯示就越流暢。瀏覽器的 fps 一般等于屏幕的刷新率,不會(huì)超過(guò)屏幕的刷新率。
其實(shí)就是假設(shè)fps 是 60 那么1秒鐘同一個(gè)物體變化60次,那么其實(shí)對(duì)于我們?nèi)搜蹃?lái)說(shuō),肯定是無(wú)法發(fā)發(fā)現(xiàn)的,那么看起來(lái)就變成了動(dòng)畫(huà)了。其實(shí)這就是動(dòng)畫(huà)的本質(zhì).
緩動(dòng)函數(shù)
什么是緩動(dòng)函數(shù)????
「緩動(dòng)函數(shù)」指定動(dòng)畫(huà)效果在執(zhí)行時(shí)的速度,使其看起來(lái)更加真實(shí)。
現(xiàn)實(shí)物體照著一定節(jié)奏移動(dòng),并不是一開(kāi)始就移動(dòng)很快的。當(dāng)我們打開(kāi)抽屜時(shí),首先會(huì)讓它加速,然后慢下來(lái)。當(dāng)某個(gè)東西往下掉時(shí),首先是越掉越快,撞到地上后回彈,最終才又碰觸地板。
正??赡苡玫降木褪蔷€性變化 linear

其實(shí)還有很多種變化有ease... 直接看圖:

實(shí)現(xiàn)原理:都是使用的cubic-bezier ?也就是三階貝塞爾曲線去做實(shí)現(xiàn)的。
生成煙霧粒子
文中的粒子其實(shí)都是three.js 中的planeGeometry 然后去貼一個(gè)煙霧的貼圖, 我先給大家看下貼圖:

貼圖的話其實(shí)就是紋理,然后直接去創(chuàng)建材質(zhì),去創(chuàng)建材質(zhì)去附到plane 上,然后呢 因?yàn)槭窃诋?huà)布中隨機(jī)嘛, 然后每一個(gè)mesh 的position 都是隨機(jī)改變的,然后就可以在頁(yè)面的創(chuàng)建很多煙霧粒子了。
??const?smokeMaterial?=?new?THREE.MeshLambertMaterial({
??????color:?new?THREE.Color(0x00dddd),
??????map:?smokeTexture,
??????transparent:?true,
????})
????const?smokeGeo?=?new?THREE.PlaneGeometry(width????100,?height????100)
????for?(let?p?=?0;?p???????const?particle?=?new?THREE.Mesh(smokeGeo,?smokeMaterial)
??????particle.position.set(Math.random()?*?500?-?250,?Math.random()?*?500?-?250,?Math.random()?*?1000?-?100)
??????particle.rotation.z?=?Math.random()?*?360
??????this.scence.add(particle)
??????this.smokeParticles.push(particle)
????}
動(dòng)畫(huà)
動(dòng)畫(huà)的話其實(shí)很簡(jiǎn)單,就是在每一幀渲染的時(shí)候,讓每一個(gè)粒子的z軸不斷去加一個(gè)數(shù)值,然后就可以實(shí)現(xiàn)這樣的效果, 因?yàn)槲疫@里是線性變化的。你可以加任何緩動(dòng)函數(shù)去修改每一個(gè)粒子的位置。
??let?sp?=?this.smokeParticles.length
??while?(sp--)?{
????this.smokeParticles[sp].rotation.z?+=?0.002
??}
總結(jié)
其實(shí)這篇文章我想講的不是如何去做這個(gè)煙霧效果,我想你能夠明白,拿到一個(gè)動(dòng)畫(huà),你該如何去拆解,去分析,至于那些花里胡哨的效果,我這里可能比較簡(jiǎn)單,有的動(dòng)畫(huà)用到了著色器,其實(shí)萬(wàn)變不離其宗哇!掌握本質(zhì),沒(méi)啥做不了的。
源碼獲得
「關(guān)注公眾號(hào),私信我,就可以獲得本篇文章所有源碼」,還是一句話,紙上得來(lái)終覺(jué)淺,絕知此事要躬行。做和看始終是兩種體驗(yàn),我喜歡喜歡圖形的fly,我們下期見(jiàn)?。?/p>
