粒子可以被用来创建星星、烟雾、雨滴、灰尘、火焰等等。我们可以使用合理的帧速率来创建数千个粒子。每个粒子都是由始终面向摄影机的平面(俩个三角形)组成的。

创建粒子

创建粒子和创建网格很像,不同的是粒子使用的材质是点材质PointsMaterial和点实例Points。
下面代码为例,当实例化球缓冲几何体时,该几何体的每个顶点都将成为粒子。


/*** 粒子*/
const particlesGeometry = new THREE.SphereBufferGeometry(1,32,32)
const particlesMaterial = new THREE.PointsMaterial({//点的大小size:0.02,//开启尺寸衰减,当相机靠近时粒子变大,当相机远离时粒子变小sizeAttenuation:true})
const particles = new THREE.Points(particlesGeometry,particlesMaterial)
scene.add(particles)

创建500个粒子

需要用到自定义几何体

const particlesGeometry = new THREE.BufferGeometry()
const count = 500
const positions = new Float32Array(count*3)
for(let i = 0;i<count*3;i++){positions[i] = (Math.random()-0.5)*10
}
particlesGeometry.setAttribute('position',new THREE.BufferAttribute(positions,3))

可以得到类似星空的效果

颜色

可以通过点材质PointsMaterialcolor属性改变粒子颜色

particles.material.color = new THREE.Color('#bbffaa')

材质

想要粒子纹理贴图可以去这个网站,当然也可以试着自己做。

const textureLoader = new THREE.TextureLoader()
const particleTexture = textureLoader.load('/textures/particles/2.png')
particlesMaterial.map = particleTexture


观察上图可以发现粒子贴图挡住了后面的粒子,因此我们可以设置为将map属性改为alphaMap属性,记得开启transparent

particlesMaterial.transparent = true
particlesMaterial.alphaMap = particleTexture

观察上图可以发现设置为alphaMap后,粒子的边缘还是存在遮挡,这是因为粒子的绘制顺序与它们的创建顺序相同,而WebGL并不知道哪一个在另一个之前。当然有好几种方法可以修复该现象。

1.设置alphaTest

alphaTest是一个介于0和1之间的值,它使WebGL能够知道根据像素的透明度什么时候不去渲染该像素。默认情况下,该值为0表示无论如何都会渲染该像素。

// 将alphaTest设为0.001
particlesMaterial.alphaTest = 0.001

2.设置depthTest

当WebGL绘制粒子时,WebGL会测试正在绘制的粒子哪个更靠前,在其后面的粒子不会被绘制,在其前面的粒子会被绘制,这就造成了混乱。这被称为深度测试,可以通过alphaTest停用depth testing

// particlesMaterial.alphaTest = 0.001
particlesMaterial.depthTest = false

关闭了深度测试后,GPU就不用再去猜哪一个在前面哪一个在后面,只管无脑绘制就对了,观察下图看出效果很不错。

但是,如果场景中有其他对象或具有不同颜色的粒子,禁用深度测试可能会产生错误,我们可以往场景添加一个简单的立方体来测试。

观察上图可以发现,原本在立方体后面的粒子我们不应该看到的,但却被一同渲染绘制出来能被观察到。所以除非粒子和物体颜色相同,并且场景只有粒子,否则不推荐轻易停用深度测试。

3.设置depthWrite

正在绘制的深度被存储在一个称为深度缓冲区的位置,作为不测试粒子是否比深度缓冲区中的粒子更近的替代方案,我们可以告诉WebGL不要使用深度测试depthTest去往深度缓冲区中写入粒子。

// particlesMaterial.alphaTest = 0.001
// particlesMaterial.depthTest = false
particlesMaterial.depthWrite = false

观察下图可以发现得到满意的效果

4.blending属性

WebGL当前是在一个像素顶部绘制另一个像素,然后我们通过设置blending混合属性为THREE.AdditiveBlending,可以告诉WebGL将像素的颜色添加到已经绘制完的像素的颜色上去,这样不同像素的颜色将会混合到一块而不是说处于前面的像素颜色会覆盖掉后面的像素颜色。

// particlesMaterial.alphaTest = 0.001
// particlesMaterial.depthTest = false
particlesMaterial.depthWrite = false
particlesMaterial.blending = THREE.AdditiveBlending

可以看到圆环相交处非常高亮,这是多个像素颜色混合的结果,或者对比下图立方体与上图立方体区域的区别,下图位于立方体前面的圆环因为颜色混合以至于我们看到的是整块白色区域,而上图由于我们没有设置blending,所以我们可以看清楚看到立方体前面的圆环。
注意,此设置会影响运行性能

为每个粒子设置不同颜色

与设置随机位置一样道理,不够这次数组里放的不是位置xyz的值,而是颜色rgb的值,然后几何体通过setAttribute方法设置color属性

const colors = new Float32Array(count*3)
for(let i = 0;i<count*3;i++){......colors[i]=Math.random()
}
particlesGeometry.setAttribute('color',new THREE.BufferAttribute(colors,3))

之后设置材质的vertexColors属性为true开启顶点着色

particlesMaterial.vertexColors = true


可以观察到还是有个主色调,因为我们前面设置了圆环的颜色,导致颜色混合了,将圆环颜色去掉后再观察便正常了

// particlesMaterial.color = new THREE.Color('#ff88cc')

动画

Points类继承于Object3D类,因此我们可以把这些点当作一个整体去移动、旋转或缩放

/*** Animate*/
const clock = new THREE.Clock()const tick = () =>
{const elapsedTime = clock.getElapsedTime()// Update controlscontrols.update()// 更新粒子particles.rotation.y = elapsedTime * 0.2// Renderrenderer.render(scene, camera)// Call tick again on the next framewindow.requestAnimationFrame(tick)
}

观察到这些点全都缓慢绕着y轴旋转

但是我们想要的是其中每一个粒子做动画而不是把它们当作一个整体去做动画。
因此,我们可以在particlesGeometry.attributes.position.array中分别更新每个顶点,因为这个数组包含了所有粒子的位置信息。

// 更新粒子// particles.rotation.y = elapsedTime * 0.2for (let i = 0; i < count; i++) {// 顶点索引const i3 = i * 3//i3+0便是每个顶点的x值,i3+1便是每个顶点的y值,i3+2便是每个顶点的z值particlesGeometry.attributes.position.array[i3 + 1] = Math.sin(elapsedTime)}


会发现所有粒子平面扁平化了一动不动,没有任何移动现象,这是因为当几何体的属性有所变化时,我们需要告诉Three.js几何体属性更新了。
因此我们需要将几何体position属性的needsUpdate设为true。

  //在循环体外面particlesGeometry.attributes.position.needsUpdate = true

然后我们会看到整个粒子构成的平面整体在上下移动,然而我们需要的是波浪效果。
因此可以对sin设置偏移量,这样便可以得到波形,这里我们使用x坐标作为其偏移量

for (let i = 0; i < count; i++) {const i3 = i * 3const x = particlesGeometry.attributes.position.array[i3 + 0]particlesGeometry.attributes.position.array[i3 + 1] = Math.sin(elapsedTime + x)}

总结

然而我们应该避免这种做法,因为在每个帧上去更新整个属性对于性能损耗非常巨大。设置粒子动画的最佳方法是创建我们自己的自定义着色器custom shader,我们将在后面的课程中这样做。

three.js学习笔记(七)——粒子相关推荐

  1. Vue.js 学习笔记 七 控制样式

    Vue.js可以灵活的控制样式 我们首先随便写2个样式 <style>.divCss {background-color: green;width:400px;height:400px;} ...

  2. Node.js学习笔记(七)#Express框架

    目录 一.Express框架简介 二.安装和使用 1.安装 2.用express创建基本Web服务器 三.Express路由 1.路由概念 2.创建基本路由 ①.创建一个简单的get路由 ② 创建一个 ...

  3. Vue.js 学习笔记 八 v-for

    v-for指令,是用来循环的,常用的情况有以下4种 <div id="divApp"><!--迭代数字--><p v-for="n in 5 ...

  4. window的dos命令学习笔记 七

    文章目录 一.dos历史学习笔记(后期整合到这里,我想能学到这里的应该不多了,嘿嘿,加油) 二.执行状态返回值(`%errorlevel%`,和shell中`$?`相似): 三.视窗 1.color ...

  5. Vue.js学习系列七——Vue服务器渲染Nuxt学习

    我又回来啦~这次我们来学习Vue的服务器渲染SSR. 关于SSR的文章网上很多,一开始看得我云里雾里.然后去Vue.js 服务器渲染指南和nuxt官网看了看,发现文章大多都是搬运官网的内容,真正讲的清 ...

  6. ArcGIS JS 学习笔记4 实现地图联动

    原文:ArcGIS JS 学习笔记4 实现地图联动 1.开篇 守望屁股实在太好玩了,所以最近有点懒,这次就先写个简单的来凑一下数.这次我的模仿目标是天地图的地图联动. 天地的地图联动不仅地图有联动,而 ...

  7. backbone.js学习笔记

    backbone.js学习笔记 之前只接触过jQuery,看来Backbone是除了jQuery的第二大JS框架... backbone到底是个啥? 其实刚开始我也不知道=_=,我是这周二才听说居然还 ...

  8. node.js学习笔记

    # node.js学习笔记标签(空格分隔): node.js---## 一 内置模块学习 ### 1. http 模块 ``` //1 导入http模块 const http =require('ht ...

  9. Typescript 学习笔记七:泛型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

最新文章

  1. python字典导入mongodb_Python中的有序字典:添加到MongoDB
  2. 我玩《王者荣耀》、斗地主、打麻将,但我是正经搞AI的北大教授
  3. 2017-2018-1 20155202 《信息安全系统设计基础》第10周学习总结
  4. 我的机器学习和深度学习绘图模板.pptx
  5. greenfoot推箱子怎么做_地推需要怎么准备,才能保证地推做最有效
  6. 自用开源/免费软件收集
  7. 模板标签及模板的继承与引用
  8. 企业文档管理_为什么这么多企业文档如此糟糕?
  9. formSelects使用
  10. Android开发笔记(一百七十九)避免方法数过多的问题
  11. python中文视频教程-鱼C零基础入门 Python中文视频教程
  12. mybatis 多表插入_CRUD_Operator-Mybatis
  13. php中conf,php 中 php-fpm.conf
  14. 硬盘分区之MBR讲解
  15. 计算机名称缩写大全集,求《魔兽世界》副本名称常用缩写大全?
  16. 纤亿通谈大型数据中心互联之T级光传输解决方案
  17. 有关安装vuex报错error found vue@2.6.14及有关vue搭建项目问题
  18. pythonembed版是什么意思_HTML中embed什么意思?有哪些作用?(附代码)
  19. Unity SWS自动寻路插件
  20. 第十二届蓝桥杯省赛C/C++B组2021

热门文章

  1. java mye,JAVA-MyEclipse第一个实例
  2. 系统工程理论与实践投稿经验_【系统工程理论与实践杂志】投稿经验与期刊点评_审稿、版面费用_退稿_要求与流程_影响因子_级别_发行周期_见刊时间_极作期刊...
  3. web前端开发工程师的竞争力体现在哪里?
  4. wireshark编译基于openflow1.3协议开发
  5. java实验报告(实验三)
  6. 顶尖量化交易公司 CEO 如何缔造量化金融王国?
  7. 做为一名程序员应该有的的好习惯
  8. PROCAST-重力铸造分析流程
  9. python zipfile压缩文件夹
  10. 读完这本书打通了“数据化运营”的任督二脉