【问题标题】:Three.js - repositioning vertices in a 'particle' meshThree.js - 在“粒子”网格中重新定位顶点
【发布时间】:2021-10-23 13:13:38
【问题描述】:

我有一个基本的 three.js 游戏,我想添加粒子。我一直在网上搜索,包括这里的多个问题,最接近“粒子系统”工作的方法是使用 THREE.BufferGeometry、THREE.BufferAttribute 和 THREE.Points 网格。我是这样设置的:

const particleMaterial = new THREE.PointsMaterial( { size: 10, map: particleTexture, blending: THREE.AdditiveBlending, transparent: true } );
const particlesGeometry = new THREE.BufferGeometry;
const particlesCount = 300;
const posArray = new Float32Array(particlesCount * 3);

for (let i = 0; i < particlesCount; i++) {
    posArray[i] = Math.random() * 10;
}

const particleBufferAttribute = new THREE.BufferAttribute(posArray, 3);
particlesGeometry.setAttribute( 'position', particleBufferAttribute );

const particlesMesh = new THREE.Points(particlesGeometry, particleMaterial);
particlesMesh.counter = 0;
scene.add(particlesMesh);

这部分工作并在粒子的初始位置很好地显示粒子,但我当然想移动它们。 我已经尝试了各种方法,在我的“动画”功能中,但我没有发生正确的组合。我想移动粒子,理想情况下每帧一个顶点。 我在动画功能中正在做的当前事情 - 不起作用! - 是这样的:

particleBufferAttribute.setXYZ( particlesMesh.counter, objects[0].position.x, objects[0].position.y, objects[0].position.z );
particlesGeometry.setAttribute( 'position', particleBufferAttribute );
//posArray[particlesMesh.counter] = objects[0].position;
particlesMesh.counter ++;
if (particlesMesh.counter > particlesCount) {
     particlesMesh.counter = 0;
}

如果有人对如何移动 Points 网格顶点有任何指示,那就太好了。

或者,如果这根本不是正确的方法,请告诉我。

我确实找到了 Stemkoski 的 ShaderParticleEngine,但我找不到任何有关如何使其工作的信息(文档非常少,似乎不包含示例)。

【问题讨论】:

    标签: three.js particle-system


    【解决方案1】:

    你不需要重新设置属性,但是你需要告诉渲染器属性已经改变了。

    particleBufferAttribute.setXYZ( particlesMesh.counter, objects[0].position.x, objects[0].position.y, objects[0].position.z );
    particleBufferAttribute.needsUpdate = true; // This is the kicker!
    

    通过将needsUpdate 设置为true,渲染器知道将该属性重新上传到GPU。

    这可能与您无关,但要知道以这种方式移动粒子很昂贵,因为您重新上传了position 属性每一帧,其中包括所有位置数据对于你没有移动的每一个粒子。

    【讨论】:

    • 好的,谢谢。很高兴知道。是的,性能是一个问题。您知道更快的方法可能是什么吗?我尝试了另一个示例,但该方法包括一个现在无法识别的 THREE.Geometry,并且用 THREE.BufferGeometry 替换它不起作用。再次感谢任何有关如何更好地做到这一点的建议!
    • @moosefetcher 这取决于你想要的效果。如果您希望所有粒子围绕一个点运行,则将该点作为Points 对象的中心,然后旋转整个对象。如果您的动画遵循某种模式,那么最好将该模式编程到顶点着色器中,通过制服传递“时间”值。如果您只移动粒子的一个子集,您可以只将这些粒子分解为它们自己的Points,以最大限度地减少属性更改开销。等等等等……
    • 在本例中,我添加了一艘宇宙飞船的“轨迹”,以便在每个顶点重置时将其位置设置为飞船的位置。我现在遇到了另一个问题,只有当我的相机定向到某些旋转时才能看到轨迹,我没有使用 OrbitControls,我让它在 Z 轴上以鼠标滚轮控制的速度移动。但显示问题可能是另一个问题。
    • @moosefetcher 确实,这是另一个问题。我想我理解——你想要一组滚动的点位。你真的需要积分吗?你可以使用Sprites 的集合吗?同样,这个话题超出了这个问题的范围,但值得深思。