Points: системы частиц

Система частиц — это мощный инструмент для создания визуальных эффектов, таких как огонь, дым, снег, дождь или абстрактные визуализации. В Three.js частицы реализуются с помощью объектов Points, которые состоят из геометрии (BufferGeometry) и материала (PointsMaterial или пользовательского ShaderMaterial).

Ключевая концепция: каждая частица — это вершина геометрии, а все вершины объединяются в один объект Points. Это позволяет GPU обрабатывать тысячи частиц эффективно, без необходимости создавать отдельные объекты для каждой.


Создание базовой системы частиц

  1. Геометрия частиц

Для системы частиц используется BufferGeometry. Основной элемент — массив координат вершин:

const particleCount = 1000;
const positions = new Float32Array(particleCount * 3);

for (let i = 0; i < particleCount; i++) {
    positions[i * 3 + 0] = (Math.random() - 0.5) * 50; // x
    positions[i * 3 + 1] = (Math.random() - 0.5) * 50; // y
    positions[i * 3 + 2] = (Math.random() - 0.5) * 50; // z
}

const geometry = new THREE.BufferGeometry();
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));

Каждая частица имеет координаты x, y, z, которые задаются случайно или по алгоритму, определяющему форму распределения.


  1. Материал частиц

Материал для частиц может быть простым или сложным. Наиболее распространённый — PointsMaterial:

const material = new THREE.PointsMaterial({
    color: 0xffffff,
    size: 0.5,
    sizeAttenuation: true, // частицы уменьшаются с удалением
    transparent: true,
    opacity: 0.8
});

Ключевые параметры:

  • size — размер каждой частицы в мировых единицах.
  • sizeAttenuation — если true, частицы уменьшаются с удалением от камеры.
  • map — текстура для частицы (например, круглая точка, спрайт огня).
  • vertexColors — позволяет использовать индивидуальные цвета для каждой частицы.

  1. Создание объекта Points
const particles = new THREE.Points(geometry, material);
scene.add(particles);

Объект Points объединяет геометрию и материал и может перемещаться, вращаться или масштабироваться как любой другой объект Three.js.


Управление поведением частиц

Системы частиц становятся динамическими при обновлении вершин в анимации:

function animateParticles() {
    const positions = geometry.attributes.position.array;
    for (let i = 0; i < particleCount; i++) {
        positions[i * 3 + 1] -= 0.1; // движение вниз
        if (positions[i * 3 + 1] < -25) positions[i * 3 + 1] = 25; // зацикливание
    }
    geometry.attributes.position.needsUpdate = true;
}

Замечания:

  • Для производительности обновляется только атрибут position.
  • Можно добавлять дополнительные атрибуты, например velocity, lifetime, color.

Использование индивидуальных цветов и размеров

Для более сложных эффектов каждая частица может иметь собственный цвет и размер:

const colors = new Float32Array(particleCount * 3);
const sizes = new Float32Array(particleCount);

for (let i = 0; i < particleCount; i++) {
    colors[i * 3 + 0] = Math.random(); // r
    colors[i * 3 + 1] = Math.random(); // g
    colors[i * 3 + 2] = Math.random(); // b
    sizes[i] = Math.random() * 1.5 + 0.5;
}

geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
geometry.setAttribute('size', new THREE.BufferAttribute(sizes, 1));

const material = new THREE.PointsMaterial({
    vertexColors: true,
    size: 0.5,
    transparent: true
});

Для управления размером каждой частицы в зависимости от атрибута используется ShaderMaterial с кастомным шейдером.


Кастомные шейдеры для частиц

Использование ShaderMaterial открывает возможность создавать сложные эффекты: пульсацию, вращение, изменение цвета с течением времени, симуляцию ветра или турбулентности.

Пример простого шейдера:

const material = new THREE.ShaderMaterial({
    uniforms: {
        time: { value: 0 },
        texture: { value: new THREE.TextureLoader().load('particle.png') }
    },
    vertexShader: `
        attribute float size;
        varying vec3 vColor;
        void main() {
            vColor = color;
            vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
            gl_PointSize = size * (300.0 / -mvPosition.z);
            gl_Position = projectionMatrix * mvPosition;
        }
    `,
    fragmentShader: `
        uniform sampler2D texture;
        varying vec3 vColor;
        void main() {
            gl_FragColor = vec4(vColor, 1.0) * texture2D(texture, gl_PointCoord);
        }
    `,
    transparent: true,
    vertexColors: true
});

Такой подход позволяет создавать эффекты огня, магии, космической пыли с полным контролем над каждой частицей.


Оптимизация системы частиц

  • Использование InstancedBufferGeometry для тысяч частиц с индивидуальными трансформациями.
  • Минимизация пересчёта атрибутов: обновлять только те атрибуты, которые изменились.
  • Использование текстур вместо больших геометрических объектов для каждой частицы.
  • Фрустракционная culling: отключать частицы за пределами видимости камеры.

Взаимодействие с физикой и триггерными событиями

Частицы могут взаимодействовать с другими объектами сцены: отражаться, исчезать при столкновении, изменять цвет или размер. Для этого используются:

  • массивы позиции и скорости каждой частицы;
  • функции обработки столкновений;
  • интеграция с библиотеками физики, такими как Cannon.js или Ammo.js, для реалистичной динамики.

Практическое применение

Системы частиц в Three.js применяются для:

  • визуализации огня, дыма, воды, снега, дождя;
  • создания космических и магических эффектов;
  • визуализации данных и графов в 3D;
  • анимаций интерфейсов и интерактивных сцен с большим числом объектов.

Эффективная реализация требует сочетания правильной геометрии, материалов и шейдеров, а также оптимизации обновлений атрибутов.