【Three.js基础学习】13.Particle

devtools/2024/11/13 10:37:17/

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

课堂知识点

        1.粒子

        2.PointsMaterial 点材质 ; 可以设置点材质的

         size 大小 , sizeAttenuation 设置这个可以 可以实现缩放粒子 近处的大 远处小,设置false 远近都一样大

        3. Points() 点网格 ,和Mesh()类似 参数接收几何体 和 材质

        注意:使用缓冲几何体 你在画面中什么也看不到;可以先从ShpereGeomatry观看一下效果

        4. 想要随机的粒子

        https://www.kenney.nl/assets/particle-pack

        需要Float32Array 获取数组长度 ,由于一个粒子是 x,y,z 数据 因此在数组中占三位

        如果要500个粒子 则 要 500 * 3

        const position = new Float32Array(count * 3)

        这个时候position 就是相当于500 个 粒子的位置信息

        position[i] = Math.random()  // 设置粒子位置的随机

        // 和上一节对比 都是设置属性 位置, 创建缓冲属性 设置位置数据 和 3

        particleGeometry.setAttribute(

            'position',

            new THREE.BufferAttribute(position,3)

        )

        添加纹理

        可以看到粒子生成 ,但是仔细看背景 是有黑色的背景 要解决

        解决方法:

            aplhaMap 属性 设置

            1. aplhaTest = 0.01 // 阿尔法 测试

                但是不是很完美

            2. depthTest = false // 深度测试  它会判断当前粒子前方是否有东西 有测渲染 不然不渲染

             会有问题 ,有其他的颜色 会很糟糕

            3.depthWrite = false // 深度缓冲区

                当绘画这些东西时候 他会判断 在这个物体前还是后 ,会有这些信息

                可以高度网格 不要在深度缓冲区进行绘画

            前三个对于性能不会影响

           

            4.blending 混合  对于性能有点影响

                depthWrite = false

                blending = THREE.AdditiveBlending

       

        设置粒子颜色不同

            1.color 存储不同颜色信息

            2.vertexColors = true  // 通知

            但是particleMaterial.color = new THREE.Color('#ff88cc') 会影响设置的颜色 。有一种混合色的柑橘

       

        动画效果

            控制每个粒子如何做

            关键在于存储的粒子信息  particleGeometry。attribute.position.array

            particleGeometry.attributes.position.needsUpdate = true

            自定义着色器

                更好的性能

            上述进行动画 会有更大的性能消耗 不好

            如果想要正确 必须创建自己的材质 ,创建自己的着色器


一、代码

javascript">import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import * as dat from 'lil-gui'
import { Mesh } from 'three'/*** Base*/
// Debug
const gui = new dat.GUI()// Canvas
const canvas = document.querySelector('canvas.webgl')// Scene
const scene = new THREE.Scene()/*** Textures*/
const textureLoader = new THREE.TextureLoader()
const particlesTexture = textureLoader.load('/textures/particles/2.png')/* 
*   Particles 粒子
*/
const particleGeometry = new THREE.BufferGeometry(1,32,32)
const count = 50000const position = new Float32Array(count * 3)
const color = new Float32Array(count * 3)
for(let i=0;i<count * 3;i++){position[i] = (Math.random() - 0.5) * 10color[i] = Math.random() 
}
particleGeometry.setAttribute('position',new THREE.BufferAttribute(position,3)
)
particleGeometry.setAttribute('color',new THREE.BufferAttribute(color,3)
)const particleMaterial = new THREE.PointsMaterial()
particleMaterial.size = 0.1
particleMaterial.sizeAttenuation = true
particleMaterial.color = new THREE.Color('#ff88cc')
// particleMaterial.map = particlesTextureparticleMaterial.transparent = true
particleMaterial.alphaMap = particlesTexture
// particleMaterial.alphaTest = 0.01
// particleMaterial.depthTest = false
particleMaterial.depthWrite = false
particleMaterial.blending = THREE.AdditiveBlending
particleMaterial.vertexColors = trueconst particles = new THREE.Points(particleGeometry,particleMaterial
)scene.add(particles)/* cube
*/
const cube = new THREE.Mesh(new THREE.BoxGeometry(),new THREE.MeshBasicMaterial()
)
// scene.add(cube)/*** Sizes*/
const sizes = {width: window.innerWidth,height: window.innerHeight
}window.addEventListener('resize', () =>
{// Update sizessizes.width = window.innerWidthsizes.height = window.innerHeight// Update cameracamera.aspect = sizes.width / sizes.heightcamera.updateProjectionMatrix()// Update rendererrenderer.setSize(sizes.width, sizes.height)renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})/*** Camera*/
// Base camera
const camera = new THREE.PerspectiveCamera(75, sizes.width / sizes.height, 0.1, 100)
camera.position.z = 3
scene.add(camera)// Controls
const controls = new OrbitControls(camera, canvas)
controls.enableDamping = true/*** Renderer*/
const renderer = new THREE.WebGLRenderer({canvas: canvas
})
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))/*** Animate*/
const clock = new THREE.Clock()const tick = () =>
{const elapsedTime = clock.getElapsedTime()// Update particles// particles.rotation.y = elapsedTime * 0.2for(let i =0 ;i<count ; i++){const i3 = i * 3const x = particleGeometry.attributes.position.array[i3] // 粒子 x的位置particleGeometry.attributes.position.array[i3 + 1] = Math.sin(elapsedTime + x)}particleGeometry.attributes.position.needsUpdate = true // 告诉three.js设置好了 要更新// Update controlscontrols.update()// Renderrenderer.render(scene, camera)// Call tick again on the next framewindow.requestAnimationFrame(tick)
}tick()

二、知识点

1.PointsMaterial 点材质

size 大小 , sizeAttenuation 设置这个可以 可以实现缩放粒子 近处的大 远处小,设置false 远近都一样大
javascript">particleMaterial.size = 0.1
particleMaterial.sizeAttenuation = true

设置颜色和纹理

javascript">particleMaterial.color = new THREE.Color('#ff88cc')
particleMaterial.map = particlesTexture

为什么可以生成多个粒子

Float32Array  获取数组长度 由于一个粒子是 x,y,z 数据 因此在数组中占三位

如果要500个粒子 则 要 500 * 3

其中变量position 的位置 可以设置 然后 每三个数组元素组成一个粒子

然后就需要设置几何体的属性 如 颜色 和 位置

particleGeometry.setAttribute(

    'position',

    new THREE.BufferAttribute(position,3)

)

particleGeometry.setAttribute(

    'color',

    new THREE.BufferAttribute(color,3)

)

同样生成不同颜色的粒子也是这样

不过要设置vertexColors = true 通知 不然不会渲染上去

javascript">const particleGeometry = new THREE.BufferGeometry(1,32,32)
const count = 50000const position = new Float32Array(count * 3)
const color = new Float32Array(count * 3)
for(let i=0;i<count * 3;i++){position[i] = (Math.random() - 0.5) * 10color[i] = Math.random() 
}
particleGeometry.setAttribute('position',new THREE.BufferAttribute(position,3)
)
particleGeometry.setAttribute('color',new THREE.BufferAttribute(color,3)
)const particleMaterial = new THREE.PointsMaterial()
particleMaterial.size = 0.1
particleMaterial.sizeAttenuation = true
particleMaterial.color = new THREE.Color('#ff88cc') // 这里颜色可以去掉 不去掉会影响设置的颜色 ,混合色
particleMaterial.vertexColors = true

让我们再把纹理添加上

仔细看有背景 纯黑色的 ,但是我想要去掉,因为这样效果不是很好

这个时候有很多方法可以去除

解决方法

1.aplhaMap  将纹理设置成阿尔法,同时设置alphaTest   

javascript">const particleGeometry = new THREE.BufferGeometry(1,32,32)
const count = 50000const position = new Float32Array(count * 3)
const color = new Float32Array(count * 3)
for(let i=0;i<count * 3;i++){position[i] = (Math.random() - 0.5) * 10color[i] = Math.random() 
}
particleGeometry.setAttribute('position',new THREE.BufferAttribute(position,3)
)
particleGeometry.setAttribute('color',new THREE.BufferAttribute(color,3)
)const particleMaterial = new THREE.PointsMaterial()
particleMaterial.size = 0.1
particleMaterial.sizeAttenuation = true
particleMaterial.color = new THREE.Color('#ff88cc')particleMaterial.transparent = true
particleMaterial.alphaMap = particlesTexture
particleMaterial.alphaTest = 0.01  // 属于缩小 边缘范围 得到类似的效果particleMaterial.vertexColors = trueconst particles = new THREE.Points(particleGeometry,particleMaterial
)scene.add(particles)

效果不是很好 仔细看圆圈重叠处有黑色的边界。

2.同上 不过将阿尔法测试属性 换成 depthTest = false 

javascript">particleMaterial.depthTest = false // 深度测试  它会判断当前粒子前方是否有东西 有测渲染 不然不渲染

看起来边缘什么的还可以 ,不过在其他颜色会有问题

可以看到颜色有种透视的感觉!

3.depthWrite 

因此我们可以设置另一个属性深度缓冲区,可以看到在白色后面的颜色没有显示

javascript">const particleGeometry = new THREE.BufferGeometry(1,32,32)
const count = 50000const position = new Float32Array(count * 3)
const color = new Float32Array(count * 3)
for(let i=0;i<count * 3;i++){position[i] = (Math.random() - 0.5) * 10color[i] = Math.random() 
}
particleGeometry.setAttribute('position',new THREE.BufferAttribute(position,3)
)
particleGeometry.setAttribute('color',new THREE.BufferAttribute(color,3)
)const particleMaterial = new THREE.PointsMaterial()
particleMaterial.size = 0.1
particleMaterial.sizeAttenuation = true
particleMaterial.color = new THREE.Color('#ff88cc')  // 这里可以去掉particleMaterial.transparent = true
particleMaterial.alphaMap = particlesTexture/*当绘画这些东西时候 他会判断 在这个物体前还是后 ,会有这些信息可以高度网格 不要在深度缓冲区进行绘画
*/
particleMaterial.depthWrite = false  // 这里 const particles = new THREE.Points(particleGeometry,particleMaterial
)scene.add(particles)

     前三个对于性能不会影响

4.blending

javascript">const particleGeometry = new THREE.BufferGeometry(1,32,32)
const count = 50000const position = new Float32Array(count * 3)
const color = new Float32Array(count * 3)
for(let i=0;i<count * 3;i++){position[i] = (Math.random() - 0.5) * 10color[i] = Math.random() 
}
particleGeometry.setAttribute('position',new THREE.BufferAttribute(position,3)
)
particleGeometry.setAttribute('color',new THREE.BufferAttribute(color,3)
)const particleMaterial = new THREE.PointsMaterial()
particleMaterial.size = 0.1
particleMaterial.sizeAttenuation = true
particleMaterial.color = new THREE.Color('#ff88cc')particleMaterial.transparent = true
particleMaterial.alphaMap = particlesTextureparticleMaterial.depthWrite = false  // 这里 结合depthWrite 使用 效果完美 性能可能有问题
particleMaterial.blending = THREE.AdditiveBlending
particleMaterial.vertexColors = trueconst particles = new THREE.Points(particleGeometry,particleMaterial
)scene.add(particles)

2.实现波浪

下面代码主要是数学,头大了! 结合js 和中设置属性的方法

javascript">  const elapsedTime = clock.getElapsedTime()// Update particlesparticles.rotation.y = elapsedTime * 0.2for(let i =0 ;i<count ; i++){const i3 = i * 3const x = particleGeometry.attributes.position.array[i3] // 粒子 x的位置//让x的位置随时间上下波动particleGeometry.attributes.position.array[i3 + 1] = Math.sin(elapsedTime + x)}particleGeometry.attributes.position.needsUpdate = true // 告诉three.js设置好了 要更新

波动


总结

点点点。。。


http://www.ppmy.cn/devtools/34304.html

相关文章

AtCoder Beginner Contest 335 D题 Loong and Takahashi

D题&#xff1a;Loong and Takahashi 标签&#xff1a;模拟题意&#xff1a;给定奇数 n n n&#xff0c;完成蛇形填数。 ( n < 45 ) (n<45) (n<45)举个例子&#xff1a; n 5 n5 n5 1 2 3 4 5 16 17 18 19 6 15 24 T 20 7 14 23 22 21 8 13 12 11 10 9题解&#xf…

【Linux】目录和文件相关的命令,补充:centos7系统目录结构

【Linux】Linux操作系统的设计理念之一就是“一切皆文件”&#xff08;Everything is a file&#xff09;&#xff0c;即将设备、文件等都当作“文件”处理。 “文件”主要类型有&#xff1a;目录&#xff08;即文件夹&#xff09;&#xff0c;链接文档&#xff08;即快捷方式…

基于频率比模型采用arcgis的滑坡易发性评估

目录 参考视频:频率比模型地形因子处理shp文件与缓冲区地理校准填补缺失值利用模糊隶属度进行归一化易发性结果出图处理:参考视频: 1. ArcGIS滑坡易发性评价_哔哩哔哩_bilibili 2. landslides susceptibility assessemnt using frequently ration approach /滑坡敏感性制图…

AutoGroup是一种推荐场景的自动特征交互建模算法 采用了高效的分组算法 基于机器学习的选项,通过训练模型进行智能划分,确保结果的合理性。

AutoGroup AutoGroup是一种推荐场景的自动特征交互建模算法,其核心功能是基于预定义的规则或机器学习模型,自动将输入数据集分成多个组。这种分组功能可以应用于各种场景,如用户细分、市场分析、学术研究等。 在技术层面,AutoGroup采用了高效的分组算法,使得其能够在大规…

虚拟化技术 使用Vsphere Client管理ESXi服务器系统

使用Vsphere Client管理ESXi服务器系统 一、实验目的与要求 1.掌握使用vSphere Client管理ESXi主机 2.掌握将CentOS的安装介质ISO上传到ESXi存储 3.掌握在VMware ESXi中创建虚拟机 4.掌握在所创建的虚拟机中安装CentOS6.5操作系统 5.掌握给CentOS6.5安装VMware Tools 6.掌…

0x002 sqlmap的参数解析

0x002 sqlmap的参数解析 重新看到cmdLineParser()​函数 首先检测是否存在argv​,如果没有则设置为系统默认的命令行参数 再调用checkSystemEncoding()​函数来检测系统的编码设置,确保后续能够正确的处理字符编码 调用os.path.basename(argv[0])​来获取脚本的文件名,再通…

Mac 电脑安装 Raptor 流程图软件的方法

0. 安装逻辑 &#xff08;1&#xff09;运行 raptor&#xff0c;本质上需要 mac 能够运行 windows 程序&#xff0c;因此需要安装 .NET Runtime 7.0&#xff0c;这是微软程序运行必须的文件。 &#xff08;2&#xff09;运行 raptor 还需要安装依赖文件 mono-libgdiplus。 &am…

hadoop学习---Hive分桶表的机制及其查询优化方案

什么是分桶表&#xff1f; 分桶是将数据集分解成更容易管理的若干部分的一个技术&#xff0c;是比分区更为细粒度的数据范围划分。 主要是用于分文件的&#xff0c;在建表的时候&#xff0c;指定按照那些字段执行分桶操作&#xff0c;并可以设置需要分多少个桶&#xff0c;当插…