Three.js — перемещение вершин в сетке «частиц»

#three.js #particle-system

Вопрос:

У меня есть базовый three.js игра работает, и я хотел бы добавить частицы. Я искал в Интернете, включая несколько вопросов здесь, и ближе всего я подошел к тому, чтобы заставить «систему частиц» работать, используя ТРИ.буферную геометрию, атрибут ТРИ.буфера и ТРОЙКУ.Точки сетки. Я устроил это так:

 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;
}
 

Если у кого-нибудь есть какие-либо указания о том, как перемещать точки в вершинах сетки, это было бы здорово.

В качестве альтернативы, если это совсем не правильный подход, пожалуйста, дайте мне знать.

Я нашел шейдерную часть Stemkoski, но не смог найти никакой информации о том, как заставить ее работать (документы очень минимальны и, похоже, не содержат примеров).

Ответ №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 равным , визуализатор знает, что нужно повторно загрузить этот атрибут на графический процессор.

Это может вас не беспокоить, но просто знайте, что перемещение частиц таким образом обходится дорого, потому что вы повторно загружаете position атрибут каждый отдельный кадр, который включает все данные о местоположении для каждой частицы, которую вы не перемещаете.

Комментарии:

1. Хорошо, спасибо. Это приятно знать. И да, производительность вызывает беспокойство. У вас есть какие-нибудь идеи о том, каким может быть более быстрый подход? Я попробовал еще один пример, но этот подход включал в себя ТРИ. Геометрия, которая не распознается в наши дни, и замена ее на ТРИ.Буферная геометрия не сработала. Опять же, я очень ценю любые советы о том, как сделать это лучше!

2. @moosefetcher Это зависит от желаемого эффекта. Если вы хотите, чтобы все частицы вращались вокруг точки, сделайте эту точку центром вашего Points объекта и поверните все это. Если ваша анимация следует шаблону, то лучше всего запрограммировать этот шаблон в вершинном шейдере, передав значение «время» через форму. Если вы перемещаете только подмножество своих частиц, вы можете разбить только эти частицы на их собственные Points , чтобы минимизировать накладные расходы на изменение атрибутов. и так далее, и тому подобное…

3. В данном случае я добавляю «след» космического корабля, чтобы при сбросе каждой вершины ее положение было равно положению корабля. У меня сейчас другая проблема в том, что след становится видимым только тогда, когда моя камера ориентирована на определенные повороты.Я не использую орбитальные контроллеры, я заставляю ее двигаться по оси Z со скоростью, контролируемой колесом мыши. Но проблема с отображением-это, вероятно, другой вопрос.

4. @moosefetcher Действительно, это другой вопрос. И я думаю, что понимаю-вам нужен подвижный набор позиций точек. Вам действительно нужны очки для этого? Не могли бы вы вместо этого использовать коллекцию Sprite s? Опять же, тема выходит за рамки этого вопроса, но есть пища для размышлений.