Three.js 的 3D 粒子动画:群星送福

发布日期:2022-08-07 07:14    点击次数:90

”粒子动画“ 这个词巨匠可以或许常常听到,那什么是粒子动画呢?

粒子是指原子、分子等形成物体的最小单位。在 2D 中,这类最小单位是像素,在 3D 中,最小单位是顶点。

粒子动画不是指物体本身的动画,而是指这些根抵单位的动画。由是以形成物体的单位的动画,所以会有打碎重组的结果。

本文我们就来深造下 3D 的粒子动画,做一个群星送福的结果:

图片 思路阐发

3D 世界中,物体是由顶点造成,3 个顶点造成一个三角形,尔后给三角形贴上差别的纹理,这样就是一个三维模型。

也就是说,3D 模型是由顶点肯定的几许体(Geometry),贴上差别的纹理(Material)所变成的物体(Mesh 等)。

当前,把 3D 物体增加参加景(Scene)中,配置一个相机(Camera)角度去窥察,尔后用衬着器(Renderer)一帧帧衬着进去,这就是 3D 衬着流程。

3D 物体是由顶点造成,那让这些顶点动起来就是粒子动画了,因为根抵粒子动了,自然就会有打碎重组的结果。

在“群星送福”结果中,我们由群星打碎重形成为了福字,事实上就是群星的顶点静止到了福字的顶点,由一个 3D 物体变成为了另外一个 3D 物体。

那末群星的顶点从何处来的?福字的顶点又怎么来呢?

群星的顶点理论上是随机生成的差别职位地方的点,在这些点上贴上星星的贴图,就是群星结果。

福字的顶点是加载的一个 3D 模型,剖析出它的顶点数据拿到的。

有了两个 3D 物体的顶点数据,也就是有了动画的起头终止坐标,那末接续的编削每个顶点的 x、y、z 属性就能实现粒子动画。

这里的 x、y、z 属性值的变换不要本身算,用一些动画库来算,它们支持减速、减速等时光函数。Three.js 的动画库是 Tween.js。

总之,3D 粒子动画就是顶点的 x、y、z 属性的变换,会用动画库来计算中央的属性值。由一个物体的顶点职位地方、静止到另外一个物体的顶点职位地方,会有种打碎重组的结果,这也是粒子动画的魅力。

思路理清了,那我们来具体写下代码吧。

代码实现

如前面所说,3D 的衬着需求一个场景(Scene)来打点全体的 3D 物体,需求一个相机(Camera)在差别角度窥察,还需求衬着器(Renderer)一帧帧衬着进去。

这部份是根抵代码,先把这部份写好:

创态度景:

const scene = new THREE.Scene(); 

创立相机:

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

相机分为透视相机战役行相机,我们这里用的透视相机,也就是近大远小的透视结果。要指定可以或许看到的视野角度(45)、宽高比(width/height)、远近领域(0.1 到 1000)这 3 种参数。

调整下相机的职位地方和窥察倾向:

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

尔后是衬着器:

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

衬着器要经由过程 requestAnimationFrame 来一帧帧的衬着:

function render() {     renderer.render(scene, camera);     requestAnimationFrame(render); } render(); 

操办事变实现,接上去就是绘制星空、福字这两种 3D 物体,另有实现粒子动画了。

绘制星空

星空不是正方体、圆柱体这类划定端方的几许体,而是由一些随机的顶点变成的,这类肆意的几许体运用缓冲几许体 BufferGeometry 创立。

为啥这类由肆意顶点变成的几许体叫缓冲几许体呢?

因为顶点在被 GPU 衬着从前是放在缓冲区 buffer 中的,所以这类指定一堆顶点的几许体就被叫做 BufferGeometry。

我们创立 30000 个随机顶点:

const vertices = []; for ( let i = 0; i < 30000; i ++ ) {     const x = THREE.MathUtils.randFloatSpread( 2000 );     const y = THREE.MathUtils.randFloatSpread( 2000 );     const z = THREE.MathUtils.randFloatSpread( 2000 );     vertices.push( x, y, z ); } 

这里用了 Three.js 供应的器材 MathUtils 来生成 0 到 2000 的随机值。

尔后用这些顶点创立 BufferGeometry:

const geometry = new THREE.BufferGeometry(); geometry.setAttribute( 'position',人才猎头 new THREE.Float32BufferAttribute(vertices, 3)); 

给 BufferGeometry 工具配置顶点职位地方,指定 3 个数值(x、y、z)为一个坐标。

尔后创立这些顶点上的材质(Material),也就是星星的贴图:

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

顶点有了,材质有了,就能创立 3D 物体了(这里的 3D 物体是 Points)。

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

看下衬着的结果:

动静的没 3D 的感到,我们让每一帧转一下,改下 render 逻辑:

function render() {     renderer.render(scene, camera);     scene.rotation.y += 0.001;      requestAnimationFrame(render); } 

再来看一下:

图片

3D 星空的感到有了!

接上去我们来做粒子动画:

3D 粒子动画

3D 粒子动画就是顶点的动画,也就是 x、y、z 的变换。

我们先来实现个最俭朴的结果,让群星都静止到 0,0,0 的职位地方:

肇端点坐标就是群星的的原有的职位地方,经由过程 getAttribute('position') 来取。动画进程运用 tween.js 来计算:

const startPositions = geometry.getAttribute('position');  for(let i = 0; i< startPositions.count; i++) {     const tween = new TWEEN.Tween(positions);      tween.to({         [i * 3]: 0,         [i * 3 + 1]: 0,         [i * 3 + 2]: 0     }, 3000 * Math.random());      tween.easing(TWEEN.Easing.Exponential.In);     tween.delay(3000);     tween.onUpdate(() => {         startPositions.needsUpdate = true;     });          tween.start(); } 

每个点都有 x、y、z 坐标,也就是下标为 i三、i3+一、i*3+2 的值,我们指定从群星的肇端职位地方静止到 0,0,0 的职位地方。

尔后指定了时光函数为减速(Easing.Exponential.In),3000 ms 后起头执行为画。

每一帧衬着的时光要调用下 Tween.update 来计算最新的值:

function render() {     TWEEN.update();     renderer.render(scene, camera);     scene.rotation.y += 0.001;      requestAnimationFrame(render); } 

每一帧在绘制的时光都市调用 onUpdate 的回调函数,我们在回调函数里把 positions 的 needsUpdate 配置为 true,就是陈诉 tween.js 在这一帧要更新为新的数值再衬着了。

第一个粒子动画实现!

来看下结果(我把这个结果叫做万象天引):

全体的星星粒子城市合到了一个点,这就是粒子动画典范的打碎重组感。

接上去,只需把粒子静止到福字的顶点就是我们要做的“群星送福”结果了。

福字模型的顶点必然不克不迭随机,本身画也不事实,这类普通都是在建模软件里画好,尔后导入到 Three.js 来衬着,

我找了这样一个福字的 3D 模型:

模型是 fbx 项目标,运用 FBXLoader 加载:

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

回调参数就是从 fbx 模型加载的 3D 物体,它是一个 Group(多个 3D 物体的鸠合),取出第 0 个元素的 geometry 属性,就是对应的几许体。

这样,我们就拿到了目标的顶点职位地方。

把粒子动画的终止职位地方改成福字的顶点就能了:

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

假定起头顶点职位地方相比多,逾越的部份从 0 的职位地方再来,所以要取余。

大功乐成!

这就是我们想要的粒子结果:

图片

完备代码上传到了 github:https://github.com/QuarkGluonPlasma/threejs-exercize

总结

粒子动画是形成物体的根抵单位的静止,对 3D 来说就是顶点的静止。

我们要实现“群星送福”的粒子动画,也就是从群星的顶点静止到福字的顶点。

群星的顶点可以或许随机生成,运用 BufferGeometry 创立对应的几许体。福字则是加载创立好的 3D 模型,拿到个中的顶点职位地方。

有了起头、终止职位地方,就能实现粒子动画了,进程中的 x、y、z 值运用动画库 Tween.js 来计算,可以或许指定减速、减速等时光函数。

粒子动画有种打碎重组的感到,可以或许用来做一些很炫的结果。懂患有什么是粒子动画、粒子动画中动的是什么,就算是开端独霸了。

我摘下漫天繁星,给巨匠送一份福泽,新的一年一起加油!

 



栏目分类



Powered by 【欧冠体育官方入口】 @2013-2022 RSS地图 HTML地图