程序员开发实例大全宝库

网站首页 > 编程文章 正文

ThreeJS 粒子(threejs粒子效果地球)

zazugpt 2024-10-24 19:27:36 编程文章 23 ℃ 0 评论

本文是我正在进行的中等难度 ThreeJS 教程系列的一部分。

让我们制作一些粒子。

与所有粒子系统一样,我们需要一组粒子。它们至少应该具有:位置、大小、速度和重力常数。

我们将多次制作粒子系统,以便您了解它们的工作原理,并且您可以了解为什么我们必须做出我们做出的选择。让我们从一个简单的实现开始:一个完整的 3D 对象数组,具有一些额外的速度属性,我们在每个滴答时更新。我们的伪代码如下所示:

create array of Object3D  
has position vector, start at 0,0,0  
add velocity vector, set at random x and z, y is fixed up  
add all to a group  
render as a small mesh  
on every tick  
update velocity based on acceleration of gravity  
update position based on velocity

这是创建一个充满球体的组的真正代码。

const rand = (min,max) => min + Math.random()*(max-min)
let scene, camera, renderer
let particles
const MAX = function setupScene() {
    particles = new THREE.Group()
    const geo = new THREE.SphereBufferGeometry(0.1)
    const mat = new THREE.MeshLambertMaterial({color: ‘red’})
    for(let i=0; i<MAX; i++) {
        const particle = new THREE.Mesh(geo,mat)
        particle.velocity = new THREE.Vector3(
           rand(-0.01, 0.01),
           0.06, 
           rand(-0.01, 0.01))
        particle.acceleration = new THREE.Vector3(0,-0.001,0)
        particle.position.x = rand(-1,1)
        particle.position.z = rand(-1,1)
        particle.position.y = rand(-1,-3)
        particles.add(particle)
    }
    particles.position.z = -4
    scene.add(particles)
 }

这就是我们在每个刻度上更新的方式。对于每个粒子,将加速度加到速度上,将速度加到位置上。随着时间的推移,这将移动粒子并加速它们。

function render(time) {  
particles.children.forEach(p => {  
p.velocity.add(p.acceleration)  
p.position.add(p.velocity)  
})  
renderer.render( scene, camera );  
}

image.png

所以..这确实有效,但它会很慢。

首先,我们对每个粒子都有一个完整的几何形状。如果只有几个就可以了,比如一堆气球,但是对于火和烟雾的完整粒子效果来说,这太重了,即使我们像上面那样重复使用材料和几何体。

这段代码很重的另一个原因是完整的几何和材质意味着完整的光照通道。相反,我们应该使用积分。他们被制造得很快。

版本 2

这次让我们创建一个 JS 对象的轻量级数组,并仅链接到 Points() 的位置。

const MAX = 100
function setupScene() {
    particles = []
    const geo = new THREE.Geometry()
    for(let i=0; i<MAX; i++) {
        const particle = {
            position: new THREE.Vector3(
                  rand(-1, 1),
                  rand(-1, 1),
                  rand(-1, -3)),
            velocity: new THREE.Vector3(
                  rand(-0.01, 0.01),
                  0.06,
                  rand(-0.01, 0.01)),
            acceleration: new THREE.Vector3(0, -0.001, 0),
        }
        particles.push(particle)
        geo.vertices.push(particle.position)
    }    const mat = new THREE.PointsMaterial({color:0xffffff,size: 0.1})
    mesh = new THREE.Points(geo,mat)
    mesh.position.z = -4
    scene.add(mesh)
}function render(time) {
    particles.forEach(p => {
       p.velocity.add(p.acceleration)
       p.position.add(p.velocity)
    })
    mesh.geometry.verticesNeedUpdate = true
    renderer.render( scene, camera );
 }

上面的代码看起来和我们开始的类似。主要区别在于实际上只有位置被传递给几何,因此传递给 GPU。对于每一次通过,我们都会在 Javascript 端计算新的速度和位置,然后只将新的几何图形传递给 GPU。这要快得多。

image.png

然而,我们的粒子可能会更快。我们必须始终记住基于 GPU 的图形编程的基本约束:

「改变成本」

你需要改变的东西越少,发送到 GPU 的东西就越少,这会消耗带宽。理想情况下,我们只需要在每一帧上将一个变量发送到 GPU:时间。其他一切都可以基于此计算。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表