Класс Mesh и его компоненты

Класс Mesh в PixiJS представляет собой мощный инструмент для работы с произвольными геометрическими объектами и текстурами. В отличие от стандартного спрайта (Sprite), который отображает прямоугольное изображение, Mesh позволяет создавать сложные формы, применять деформации и использовать кастомные шейдеры, сохраняя при этом высокую производительность.


Основные компоненты Mesh

Mesh состоит из нескольких ключевых элементов:

  1. Геометрия (geometry) Геометрия определяет форму объекта и состоит из вершин, индексов и дополнительных атрибутов. В PixiJS для работы с геометрией используется класс PIXI.Geometry.

    Пример структуры геометрии:

    const geometry = new PIXI.Geometry()
        .addAttribute('position', // Название атрибута
                      [0, 0, 100, 0, 100, 100, 0, 100], // Массив координат вершин
                      2) // Размерность каждой вершины
        .addAttribute('uv', [0, 0, 1, 0, 1, 1, 0, 1], 2) // Координаты текстуры
        .addIndex([0, 1, 2, 0, 2, 3]); // Индексы для треугольников

    Ключевые моменты:

    • Атрибут position определяет координаты вершин в локальной системе координат.
    • Атрибут uv отвечает за маппинг текстуры на геометрию.
    • Индексы указывают, какие вершины образуют треугольники для рендеринга.
  2. Материал (shader или Material) Материал управляет визуальной частью объекта: текстурой, цветом и шейдерами. По умолчанию можно использовать PIXI.MeshMaterial или PIXI.MeshBasicMaterial.

    Пример использования текстурного материала:

    const texture = PIXI.Texture.from('image.png');
    const material = new PIXI.MeshMaterial(texture);

    Особенности:

    • Материалы могут быть стандартными (MeshMaterial) или кастомными с пользовательскими шейдерами (PIXI.Shader).
    • Позволяют изменять прозрачность, смешивание цветов и фильтры.
  3. Вершины (vertices) Вершины – это массив чисел, задающих координаты точек геометрии. Для динамических мешей можно обновлять массив vertices, чтобы анимировать деформации или изменять форму объекта в реальном времени.

    Динамическое обновление вершин:

    mesh.geometry.getBuffer('position').update([
        0, 0, 120, 0, 120, 120, 0, 120
    ]);
  4. Координаты текстуры (uvs) uvs – это нормализованные координаты текстуры, сопоставляемые с каждой вершиной. Они позволяют контролировать, какая часть текстуры отображается на меше, и важны для создания эффектов деформации.

  5. Индексы (indices) Индексы формируют треугольники для рендеринга. Каждый треугольник определяется тремя индексами, указывающими на вершины в массиве position. Использование индексов уменьшает дублирование вершин и экономит память.


Создание и использование Mesh

Создание меша в PixiJS включает три шага: определение геометрии, создание материала и объединение их в объект Mesh.

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

const geometry = new PIXI.Geometry()
    .addAttribute('position', [0, 0, 100, 0, 100, 100, 0, 100], 2)
    .addAttribute('uv', [0, 0, 1, 0, 1, 1, 0, 1], 2)
    .addIndex([0, 1, 2, 0, 2, 3]);

const texture = PIXI.Texture.from('image.png');
const material = new PIXI.MeshMaterial(texture);

const mesh = new PIXI.Mesh(geometry, material);
app.stage.addChild(mesh);

Деформации и анимация

Меши позволяют реализовать сложные эффекты деформации, такие как волны, изгибы или морфинг:

  • Изменение вершин вручную: можно изменять позиции вершин на каждом кадре.
  • Использование шейдеров: кастомные вершинные шейдеры позволяют создавать плавные деформации без изменения массива вершин на CPU.

Пример анимации волн:

app.ticker.add((delta) => {
    const positions = mesh.geometry.getBuffer('position').data;
    for (let i = 0; i < positions.length; i += 2) {
        positions[i + 1] += Math.sin(positions[i] * 0.05 + app.ticker.lastTime * 0.01) * 0.5;
    }
    mesh.geometry.getBuffer('position').update(positions);
});

Особенности работы с большим количеством мешей

  • Использование одного материала: несколько мешей с одинаковым материалом рендерятся быстрее благодаря batching.
  • Обновление буферов: изменение атрибутов вершин через update() оптимизировано для GPU, но частые изменения больших массивов могут снижать производительность.
  • Индексы: правильно организованные индексы позволяют уменьшить количество вершин и повысить эффективность рендеринга.

Интеграция с фильтрами и эффектами

Меши полностью совместимы с фильтрами PixiJS. Например, можно применять размытие, цветокоррекцию или шейдерные эффекты:

mesh.filters = [new PIXI.filters.BlurFilter(5)];

Фильтры работают на GPU и поддерживают динамические деформации без снижения производительности, что делает меши гибким инструментом для визуализации сложных графических эффектов.


Применение кастомных шейдеров

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

const vertexShader = `
    precision mediump float;
    attribute vec2 aVertexPosition;
    attribute vec2 aTextureCoord;
    uniform mat3 projectionMatrix;
    varying vec2 vTextureCoord;

    void main() {
        vTextureCoord = aTextureCoord;
        gl_Position = vec4((projectionMatrix * vec3(aVertexPosition, 1.0)).xy, 0.0, 1.0);
    }
`;

const fragmentShader = `
    precision mediump float;
    varying vec2 vTextureCoord;
    uniform sampler2D uSampler;

    void main() {
        vec4 color = texture2D(uSampler, vTextureCoord);
        gl_FragColor = vec4(color.rgb, color.a);
    }
`;

const shader = PIXI.Shader.from(vertexShader, fragmentShader, { uSampler: texture });
const customMesh = new PIXI.Mesh(geometry, shader);

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


Взаимодействие с другими объектами сцены

Mesh поддерживает все стандартные свойства DisplayObject:

  • Позиция, масштаб, вращение
  • Альфа и видимость
  • События взаимодействия (pointer events)

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