Plane, NineSlicePlane, Rope: специализированные меши

Класс Mesh в PixiJS предоставляет низкоуровневый доступ к работе с вершинами, UV-координатами и индексами. На его основе реализованы специализированные решения для типовых задач деформации текстур: Plane, NineSlicePlane и Rope. Эти классы позволяют управлять геометрией изображения без ручной работы с буферами, сохраняя при этом производительность WebGL.


Plane: сетка с равномерной разбивкой

Назначение

Plane представляет собой прямоугольную сетку (grid), состоящую из множества сегментов по горизонтали и вертикали. Текстура распределяется по всей поверхности, а каждая вершина может быть смещена, создавая эффект искажения.

Класс применяется для:

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

Концепция сетки

При создании Plane задаются:

  • текстура;
  • количество сегментов по ширине (verticesX);
  • количество сегментов по высоте (verticesY).

Чем больше сегментов, тем выше детализация деформации. Однако увеличение числа вершин влияет на производительность, поскольку возрастает объём геометрических данных.

Внутренне создаются:

  • массив вершин (позиции XY);
  • массив UV-координат;
  • индексный буфер (треугольники).

Каждый прямоугольный сегмент разбивается на два треугольника.

Пример создания

const plane = new PIXI.SimplePlane(texture, 10, 10);

Здесь формируется сетка 10×10 сегментов. Общее количество вершин равно (10 + 1) * (10 + 1).

Работа с вершинами

Вершины хранятся в массиве:

plane.geometry.getBuffer('aVertexPosition').data

Каждые две координаты соответствуют одной вершине: [x0, y0, x1, y1, ...].

Изменение координат позволяет создавать анимации:

const vertices = plane.geometry.getBuffer('aVertexPosition').data;

for (let i = 0; i < vertices.length; i += 2) {
    vertices[i + 1] += Math.sin(i + time) * 2;
}

plane.geometry.getBuffer('aVertexPosition').update();

Обновление буфера обязательно после модификации.

Особенности производительности

  • При статической геометрии обновление буфера не требуется.
  • Частые изменения вершин увеличивают нагрузку на GPU.
  • Разумное количество сегментов критично для мобильных устройств.

NineSlicePlane: адаптивное масштабирование интерфейса

Проблема масштабирования

При масштабировании обычного спрайта происходит растяжение всей текстуры, включая углы и рамки. В интерфейсных элементах (кнопки, панели, окна) это приводит к искажению декоративных частей.

Принцип 9-сегментной разметки

NineSlicePlane делит текстуру на 9 областей:

[ A | B | C ]
[ D | E | F ]
[ G | H | I ]
  • Углы (A, C, G, I) — не масштабируются.
  • Горизонтальные края (B, H) — растягиваются по ширине.
  • Вертикальные края (D, F) — растягиваются по высоте.
  • Центр (E) — масштабируется по обоим направлениям.

Таким образом сохраняется форма углов при изменении размеров.

Создание NineSlicePlane

const panel = new PIXI.NineSlicePlane(
    texture,
    leftWidth,
    topHeight,
    rightWidth,
    bottomHeight
);

Параметры определяют размеры нерастягиваемых областей по краям текстуры.

Управление размерами

Размер меняется обычными свойствами:

panel.width = 400;
panel.height = 200;

Геометрия автоматически пересчитывается.

Внутреннее устройство

NineSlicePlane является расширением SimplePlane, но:

  • количество сегментов фиксировано (3×3);
  • вершины перераспределяются при изменении ширины/высоты;
  • UV-координаты рассчитываются с учётом фиксированных углов.

Типичные сценарии применения

  • UI-кнопки;
  • диалоговые окна;
  • панели инвентаря;
  • HUD-элементы в играх.

Ограничения

  • Поддерживается только прямоугольная форма.
  • Невозможно использовать сложные криволинейные рамки без дополнительной геометрии.
  • Текстура должна быть корректно размечена (углы фиксированного размера).

Rope: деформация вдоль произвольной кривой

Назначение

Rope используется для отображения текстуры вдоль набора точек. Геометрия формируется на основе ломаной линии, а текстура “оборачивается” вокруг неё.

Применяется для:

  • верёвок и цепей;
  • молний;
  • змей и хвостов;
  • ленточных эффектов;
  • следов движения.

Принцип работы

В основе лежит массив точек:

const points = [
    new PIXI.Point(x1, y1),
    new PIXI.Point(x2, y2),
    ...
];

Каждая точка определяет центральную линию. На основе соседних точек вычисляется:

  • направление сегмента;
  • нормаль (перпендикуляр);
  • смещённые вершины по обе стороны линии.

Фактически каждая точка порождает две вершины — левую и правую относительно направления сегмента.

Создание Rope

const rope = new PIXI.SimpleRope(texture, points);

Количество сегментов равно количеству точек минус один.

Анимация

Изменение положения точек автоматически деформирует геометрию:

for (let i = 0; i < points.length; i++) {
    points[i].y += Math.sin(i * 0.5 + time) * 3;
}

Пересчёт геометрии происходит внутри класса при рендеринге.

Распределение текстуры

UV-координаты распределяются вдоль длины ломаной. По умолчанию:

  • текстура растягивается от первой точки к последней;
  • по ширине она занимает всю высоту изображения.

При необходимости возможно ручное управление UV-буфером.

Толщина верёвки

Ширина определяется высотой текстуры. Изменение масштаба влияет на толщину:

rope.scale.y = 0.5;

Сравнение Plane, NineSlicePlane и Rope

Характеристика Plane NineSlicePlane Rope
Тип деформации Сетка 9-сегментная сетка Ломаная линия
Произвольная форма Частично Нет Да
Подходит для UI Нет Да Нет
Подходит для эффектов Да Ограниченно Да
Контроль вершин Полный Ограниченный Через точки

Геометрия и буферы

Все три класса используют общую архитектуру Mesh:

  • Geometry — хранит атрибуты вершин;
  • Buffer — передаёт данные в GPU;
  • Shader — определяет обработку фрагментов.

Атрибуты

Основные атрибуты:

  • aVertexPosition
  • aTextureCoord
  • индексный буфер

Изменение позиции вершин требует вызова update() у соответствующего буфера.

Оптимизация

  • Минимизируется частота обновления буферов.
  • Используются статические геометрии при отсутствии анимации.
  • Число сегментов выбирается исходя из требуемой точности.

Практические особенности

1. Масштабирование и pivot

При деформации важно учитывать pivot и anchor. Неправильная установка может привести к визуальным смещениям при изменении размеров.

2. Интерактивность

Меши поддерживают интерактивность, но хит-тестирование выполняется по ограничивающему прямоугольнику, а не по фактической форме. Для точных проверок требуется кастомная логика.

3. Совместимость с фильтрами

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

4. Кастомные шейдеры

Возможна замена стандартного шейдера:

const mesh = new PIXI.Mesh(geometry, customShader);

На базе Plane или Rope создаются продвинутые эффекты, включая:

  • псевдо-3D искажения;
  • волновые и шумовые трансформации;
  • динамическое освещение.

Архитектурная роль специализированных мешей

Plane, NineSlicePlane и Rope представляют промежуточный уровень между простыми спрайтами и полностью кастомной геометрией. Они:

  • избавляют от ручной работы с индексами;
  • сохраняют гибкость Mesh API;
  • оптимизированы под типовые сценарии.

Использование этих классов позволяет реализовывать сложные визуальные эффекты без написания низкоуровневого WebGL-кода, сохраняя контроль над вершинами и текстурными координатами.