О чем этот пример
Одной из сильных сторон Phaser является работа с графикой. Часто для сложных визуальных эффектов или оптимизации требуется подготовить текстуру в реальном времени, а затем использовать её как источник данных. В этом примере мы рассмотрим, как создать рендер-текстуру (Render Texture), наполнить её спрайтами и передать в шейдер для создания красивого туннельного эффекта. Этот подход полезен для генерации процедурных текстур, создания маск-объектов или подготовки данных для пост-обработки.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
function preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('apple', 'assets/sprites/apple.png');
this.load.image('metal', 'assets/textures/alien-metal.jpg');
this.load.glsl('bundle', 'assets/shaders/bundle.glsl.js');
}
function create()
{
const rt = this.add.renderTexture(0, 0, 512, 512).setVisible(false);
rt.fill(0x00066, 1, 0, 0, 512, 512);
for (var i = 0; i < 64; i++)
{
rt.draw('apple', Phaser.Math.Between(50, 462), Phaser.Math.Between(50, 462));
}
rt.saveTexture('rt');
const shader = this.add.shader('Tunnel', 400, 300, 800, 600, [ 'rt' ]);
}
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
scene: {
preload: preload,
create: create
}
};
const game = new Phaser.Game(config);
Загрузка ресурсов
В методе preload мы загружаем все необходимые ассеты для сцены. Обратите внимание на использование метода load.glsl для загрузки шейдеров.
function preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('apple', 'assets/sprites/apple.png');
this.load.image('metal', 'assets/textures/alien-metal.jpg');
this.load.glsl('bundle', 'assets/shaders/bundle.glsl.js');
}
Создание и заполнение Render Texture
В методе create мы создаем невидимую рендер-текстуру размером 512x512 пикселей с помощью this.add.renderTexture. Сначала мы заливаем её темно-синим цветом, а затем в цикле рисуем 64 случайно размещенных спрайта 'apple'.
function create()
{
const rt = this.add.renderTexture(0, 0, 512, 512).setVisible(false);
rt.fill(0x000066, 1, 0, 0, 512, 512);
for (var i = 0; i < 64; i++)
{
rt.draw('apple', Phaser.Math.Between(50, 462), Phaser.Math.Between(50, 462));
}
Ключевые методы:
- rt.fill(color, alpha, x, y, width, height) – заливка области.
- rt.draw(key, x, y) – отрисовка спрайта по ключу в заданных координатах.
- Phaser.Math.Between(min, max) – генерация случайного числа в диапазоне.
Сохранение текстуры и передача в шейдер
После подготовки рендер-текстуру необходимо сохранить в кэш текстур игры с уникальным ключом, чтобы другие системы могли её использовать. Это делается методом saveTexture. Затем мы создаем шейдерный объект, передавая ключ сохраненной текстуры в качестве входного параметра (uniform).
rt.saveTexture('rt');
const shader = this.add.shader('Tunnel', 400, 300, 800, 600, [ 'rt' ]);
}
Здесь 'Tunnel' – это имя шейдера из загруженного бандла (bundle). Массив [ 'rt' ] содержит ключи текстур, которые будут переданы шейдеру.
Настройка конфигурации игры
Для работы с шейдерами и рендер-текстурами требуется контекст WebGL. Поэтому в конфигурации игры обязательно указываем type: Phaser.WEBGL.
const config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
scene: {
preload: preload,
create: create
}
};
const game = new Phaser.Game(config);
Что попробовать дальше
Render Texture в Phaser – это мощный инструмент для оффскринного рендеринга. Вы можете комбинировать спрайты, графику и даже другие шейдеры для создания сложных текстур в реальном времени, а затем использовать их для пост-обработки или как часть игрового процесса. Для экспериментов попробуйте:
1. Изменить алгоритм заполнения рендер-текстуры (например, рисовать спрайты в сетке или по определенной форме).
2. Использовать полученную текстуру не только в шейдере, но и как спрайт для обычного this.add.image.
3. Анимировать содержимое рендер-текстуры, перерисовывая её каждый кадр в методе update.
