成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Three.js 的 3D 粒子動畫:群星送福

開發(fā) 前端
粒子動畫不是指物體本身的動畫,而是指這些基本單位的動畫。因?yàn)槭墙M成物體的單位的動畫,所以會有打碎重組的效果。

”粒子動畫“ 這個(gè)詞大家可能經(jīng)常聽到,那什么是粒子動畫呢?

粒子是指原子、分子等組成物體的最小單位。在 2D 中,這種最小單位是像素,在 3D 中,最小單位是頂點(diǎn)。

粒子動畫不是指物體本身的動畫,而是指這些基本單位的動畫。因?yàn)槭墙M成物體的單位的動畫,所以會有打碎重組的效果。

本文我們就來學(xué)習(xí)下 3D 的粒子動畫,做一個(gè)群星送福的效果:

圖片

思路分析

3D 世界中,物體是由頂點(diǎn)構(gòu)成,3 個(gè)頂點(diǎn)構(gòu)成一個(gè)三角形,然后給三角形貼上不同的紋理,這樣就是一個(gè)三維模型。

也就是說,3D 模型是由頂點(diǎn)確定的幾何體(Geometry),貼上不同的紋理(Material)所構(gòu)成的物體(Mesh 等)。

之后,把 3D 物體添加到場景(Scene)中,設(shè)置一個(gè)相機(jī)(Camera)角度去觀察,然后用渲染器(Renderer)一幀幀渲染出來,這就是 3D 渲染流程。

3D 物體是由頂點(diǎn)構(gòu)成,那讓這些頂點(diǎn)動起來就是粒子動畫了,因?yàn)榛玖W觿恿耍匀痪蜁写蛩橹亟M的效果。

在“群星送福”效果中,我們由群星打碎重組成了福字,實(shí)際上就是群星的頂點(diǎn)運(yùn)動到了福字的頂點(diǎn),由一個(gè) 3D 物體變成了另一個(gè) 3D 物體。

那么群星的頂點(diǎn)從哪里來的?福字的頂點(diǎn)又怎么來呢?

群星的頂點(diǎn)其實(shí)是隨機(jī)生成的不同位置的點(diǎn),在這些點(diǎn)上貼上星星的貼圖,就是群星效果。

福字的頂點(diǎn)是加載的一個(gè) 3D 模型,解析出它的頂點(diǎn)數(shù)據(jù)拿到的。

有了兩個(gè) 3D 物體的頂點(diǎn)數(shù)據(jù),也就是有了動畫的開始結(jié)束坐標(biāo),那么不斷的修改每個(gè)頂點(diǎn)的 x、y、z 屬性就可以實(shí)現(xiàn)粒子動畫。

這里的 x、y、z 屬性值的變化不要自己算,用一些動畫庫來算,它們支持加速、減速等時(shí)間函數(shù)。Three.js 的動畫庫是 Tween.js。

總之,3D 粒子動畫就是頂點(diǎn)的 x、y、z 屬性的變化,會用動畫庫來計(jì)算中間的屬性值。由一個(gè)物體的頂點(diǎn)位置、運(yùn)動到另一個(gè)物體的頂點(diǎn)位置,會有種打碎重組的效果,這也是粒子動畫的魅力。

思路理清了,那我們來具體寫下代碼吧。

代碼實(shí)現(xiàn)

如前面所說,3D 的渲染需要一個(gè)場景(Scene)來管理所有的 3D 物體,需要一個(gè)相機(jī)(Camera)在不同角度觀察,還需要渲染器(Renderer)一幀幀渲染出來。

這部分是基礎(chǔ)代碼,先把這部分寫好:

創(chuàng)建場景:

  1. const scene = new THREE.Scene(); 

創(chuàng)建相機(jī):

  1. const width = window.innerWidth; 
  2. const height = window.innerHeight; 
  3. const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000); 

相機(jī)分為透視相機(jī)和平行相機(jī),我們這里用的透視相機(jī),也就是近大遠(yuǎn)小的透視效果。要指定可以看到的視野角度(45)、寬高比(width/height)、遠(yuǎn)近范圍(0.1 到 1000)這 3 種參數(shù)。

調(diào)整下相機(jī)的位置和觀察方向:

  1. camera.position.set(100, 0, 400); 
  2. camera.lookAt(scene.position); 

然后是渲染器:

  1. const renderer = new THREE.WebGLRenderer(); 
  2. renderer.setSize(width, height); 
  3. document.body.appendChild(renderer.domElement); 

渲染器要通過 requestAnimationFrame 來一幀幀的渲染:

  1. function render() { 
  2.     renderer.render(scene, camera); 
  3.     requestAnimationFrame(render); 
  4. render(); 

準(zhǔn)備工作完成,接下來就是繪制星空、福字這兩種 3D 物體,還有實(shí)現(xiàn)粒子動畫了。

繪制星空

星空不是正方體、圓柱體這種規(guī)則的幾何體,而是由一些隨機(jī)的頂點(diǎn)構(gòu)成的,這種任意的幾何體使用緩沖幾何體 BufferGeometry 創(chuàng)建。

為啥這種由任意頂點(diǎn)構(gòu)成的幾何體叫緩沖幾何體呢?

因?yàn)轫旤c(diǎn)在被 GPU 渲染之前是放在緩沖區(qū) buffer 中的,所以這種指定一堆頂點(diǎn)的幾何體就被叫做 BufferGeometry。

我們創(chuàng)建 30000 個(gè)隨機(jī)頂點(diǎn):

  1. const vertices = []; 
  2. for ( let i = 0; i < 30000; i ++ ) { 
  3.     const x = THREE.MathUtils.randFloatSpread( 2000 ); 
  4.     const y = THREE.MathUtils.randFloatSpread( 2000 ); 
  5.     const z = THREE.MathUtils.randFloatSpread( 2000 ); 
  6.     vertices.push( x, y, z ); 

這里用了 Three.js 提供的工具 MathUtils 來生成 0 到 2000 的隨機(jī)值。

然后用這些頂點(diǎn)創(chuàng)建 BufferGeometry:

  1. const geometry = new THREE.BufferGeometry(); 
  2. geometry.setAttribute( 'position', new THREE.Float32BufferAttribute(vertices, 3)); 

給 BufferGeometry 對象設(shè)置頂點(diǎn)位置,指定 3 個(gè)數(shù)值(x、y、z)為一個(gè)坐標(biāo)。

然后創(chuàng)建這些頂點(diǎn)上的材質(zhì)(Material),也就是星星的貼圖:

  1. const star = new THREE.TextureLoader().load('img/star.png'); 
  2. const material = new THREE.PointsMaterial( { size: 10, map: star }); 

頂點(diǎn)有了,材質(zhì)有了,就可以創(chuàng)建 3D 物體了(這里的 3D 物體是 Points)。

  1. const points = new THREE.Points( geometry, material ); 
  2. scene.add(points); 

看下渲染的效果:

靜態(tài)的沒 3D 的感覺,我們讓每一幀轉(zhuǎn)一下,改下 render 邏輯:

  1. function render() { 
  2.     renderer.render(scene, camera); 
  3.     scene.rotation.y += 0.001; 
  4.  
  5.     requestAnimationFrame(render); 

再來看一下:

圖片

3D 星空的感覺有了!

接下來我們來做粒子動畫:

3D 粒子動畫

3D 粒子動畫就是頂點(diǎn)的動畫,也就是 x、y、z 的變化。

我們先來實(shí)現(xiàn)個(gè)最簡單的效果,讓群星都運(yùn)動到 0,0,0 的位置:

起始點(diǎn)坐標(biāo)就是群星的的本來的位置,通過 getAttribute('position') 來取。動畫過程使用 tween.js 來計(jì)算:

  1. const startPositions = geometry.getAttribute('position'); 
  2.  
  3. for(let i = 0; i< startPositions.count; i++) { 
  4.     const tween = new TWEEN.Tween(positions); 
  5.  
  6.     tween.to({ 
  7.         [i * 3]: 0, 
  8.         [i * 3 + 1]: 0, 
  9.         [i * 3 + 2]: 0 
  10.     }, 3000 * Math.random()); 
  11.  
  12.     tween.easing(TWEEN.Easing.Exponential.In); 
  13.     tween.delay(3000); 
  14.     tween.onUpdate(() => { 
  15.         startPositions.needsUpdate = true
  16.     }); 
  17.      
  18.     tween.start(); 

每個(gè)點(diǎn)都有 x、y、z 坐標(biāo),也就是下標(biāo)為 i3、i3+1、i*3+2 的值,我們指定從群星的起始位置運(yùn)動到 0,0,0 的位置。

然后指定了時(shí)間函數(shù)為加速(Easing.Exponential.In),3000 ms 后開始執(zhí)行動畫。

每一幀渲染的時(shí)候要調(diào)用下 Tween.update 來計(jì)算最新的值:

  1. function render() { 
  2.     TWEEN.update(); 
  3.     renderer.render(scene, camera); 
  4.     scene.rotation.y += 0.001; 
  5.  
  6.     requestAnimationFrame(render); 

每一幀在繪制的時(shí)候都會調(diào)用 onUpdate 的回調(diào)函數(shù),我們在回調(diào)函數(shù)里把 positions 的 needsUpdate 設(shè)置為 true,就是告訴 tween.js 在這一幀要更新為新的數(shù)值再渲染了。

第一個(gè)粒子動畫完成!

來看下效果(我把這個(gè)效果叫做萬象天引):

所有的星星粒子都集中到了一個(gè)點(diǎn),這就是粒子動畫典型的打碎重組感。

接下來,只要把粒子運(yùn)動到福字的頂點(diǎn)就是我們要做的“群星送福”效果了。

福字模型的頂點(diǎn)肯定不能隨機(jī),自己畫也不現(xiàn)實(shí),這種一般都是在建模軟件里畫好,然后導(dǎo)入到 Three.js 來渲染,

我找了這樣一個(gè)福字的 3D 模型:

模型是 fbx 格式的,使用 FBXLoader 加載:

  1. const loader = new THREE.FBXLoader(); 
  2. loader.load('./obj/fu.fbx'function (object) { 
  3.     const destPosition = object.children[0].geometry.getAttribute('position'); 
  4.  
  5. }); 

回調(diào)參數(shù)就是從 fbx 模型加載的 3D 物體,它是一個(gè) Group(多個(gè) 3D 物體的集合),取出第 0 個(gè)元素的 geometry 屬性,就是對應(yīng)的幾何體。

這樣,我們就拿到了目標(biāo)的頂點(diǎn)位置。

把粒子動畫的結(jié)束位置改為福字的頂點(diǎn)就可以了:

  1. const cur = i % destPosition.count
  2. tween.to({ 
  3.     [i * 3]: destPosition.array[cur * 3], 
  4.     [i * 3 + 1]: destPosition.array[(cur * 3 + 1)], 
  5.     [i * 3 + 2]: destPosition.array[(cur * 3 + 2)] 
  6. }, 3000 * Math.random()); 

如果開始頂點(diǎn)位置比較多,超過的部分從 0 的位置再來,所以要取余。

大功告成!

這就是我們想要的粒子效果:

圖片

完整代碼上傳到了 github:https://github.com/QuarkGluonPlasma/threejs-exercize

總結(jié)

粒子動畫是組成物體的基本單位的運(yùn)動,對 3D 來說就是頂點(diǎn)的運(yùn)動。

我們要實(shí)現(xiàn)“群星送福”的粒子動畫,也就是從群星的頂點(diǎn)運(yùn)動到福字的頂點(diǎn)。

群星的頂點(diǎn)可以隨機(jī)生成,使用 BufferGeometry 創(chuàng)建對應(yīng)的幾何體。福字則是加載創(chuàng)建好的 3D 模型,拿到其中的頂點(diǎn)位置。

有了開始、結(jié)束位置,就可以實(shí)現(xiàn)粒子動畫了,過程中的 x、y、z 值使用動畫庫 Tween.js 來計(jì)算,可以指定加速、減速等時(shí)間函數(shù)。

粒子動畫有種打碎重組的感覺,可以用來做一些很炫的效果。理解了什么是粒子動畫、粒子動畫中動的是什么,就算是初步掌握了。

我摘下漫天繁星,給大家送一份福氣,新的一年一起加油!

 

責(zé)任編輯:姜華 來源: 神光的編程秘籍
相關(guān)推薦

2019-11-29 09:30:37

Three.js3D前端

2024-07-18 06:58:36

2025-05-13 02:01:00

Three.jsSprite粒子

2021-11-27 10:42:01

Three.js3D可視化AudioContex

2021-11-23 22:50:14

.js 3D幾何體

2023-07-13 10:48:22

web 3DThree.jsBlender

2025-06-30 09:15:47

2021-04-21 09:20:15

three.js3d前端

2016-06-01 09:19:08

開發(fā)3D游戲

2021-04-23 16:40:49

Three.js前端代碼

2023-08-04 09:56:15

2023-05-03 09:01:41

CanvasWebGL

2024-02-26 00:00:00

前端工具Space.js

2022-07-15 13:09:33

Three.js前端

2021-11-22 06:14:45

Three.js3D 渲染花瓣雨

2017-05-08 11:41:37

WebGLThree.js

2023-09-01 09:30:22

Three.js3D 圖形庫

2013-01-30 16:15:40

adobeHTML5css3

2025-05-15 08:45:00

開源前端手勢

2025-03-13 10:54:18

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 天天弄天天操 | 懂色一区二区三区免费观看 | 99热最新网址 | 亚洲久久一区 | 99精品久久久久久中文字幕 | 中文字幕乱码亚洲精品一区 | 亚洲免费视频在线观看 | 久草热播 | 天堂久久网 | 日韩精品在线一区二区 | 情侣黄网站免费看 | av网站在线看 | 亚洲天堂免费 | 人人干人人看 | 中文字幕第十一页 | 免费国产精品久久久久久 | 亚洲 欧美 激情 另类 校园 | 成年人在线 | 亚洲va欧美va天堂v国产综合 | 天天曰天天曰 | 成人不卡 | 麻豆精品国产91久久久久久 | 91高清视频在线 | 精品一区二区电影 | 在线看无码的免费网站 | 中文字幕成人av | 蜜月aⅴ免费一区二区三区 99re在线视频 | 一区二区三区在线播放视频 | 国产成人久久精品一区二区三区 | 久久精品国产久精国产 | 日本不卡免费新一二三区 | 国产成人福利 | 欧美aaaa视频 | 国产网站在线 | 亚洲欧美激情国产综合久久久 | 二区在线视频 | 一区二区三区四区在线视频 | 在线看av网址 | 久久成人午夜 | 女同久久另类99精品国产 | 欧美一级全黄 |