О чем этот пример
Встроенные режимы наложения, такие как `ADD` или `MULTIPLY`, часто покрывают базовые нужды, но что если вам нужен уникальный визуальный эффект? Phaser 3 на WebGL позволяет создавать и динамически изменять собственные режимы смешивания цветов, напрямую используя возможности OpenGL. Это открывает двери для создания сложных, кастомных визуальных стилей, динамических световых эффектов или нестандартных переходов, которые невозможно реализовать стандартными средствами фреймворка. В этой статье мы разберем официальный пример, который демонстрирует, как создать свой режим наложения и управлять его параметрами в реальном времени через интерфейс. Вы научитесь работать с низкоуровневыми константами WebGL и API рендерера Phaser.
Версия Phaser: код и демо в этой статье рассчитаны на Phaser 3.90.0.
Живой запуск
Ниже встроен рабочий билд примера. Оригинальный источник: GitHub.
Исходный код
class Example extends Phaser.Scene
{
constructor ()
{
super();
}
preload ()
{
this.load.setBaseURL('https://raw.githubusercontent.com/phaserjs/examples/master/public/');
this.load.image('turkey', 'assets/pics/turkey-1985086.jpg');
this.load.image('face', 'assets/pics/bw-face.png');
this.load.image('src', 'assets/tests/blendmode/src.png');
this.load.image('dst', 'assets/tests/blendmode/dst.png');
}
create ()
{
// WebGL only:
var gl = this.sys.game.renderer.gl;
var consts = [
gl.ZERO,
gl.ONE,
gl.SRC_COLOR,
gl.ONE_MINUS_SRC_COLOR,
gl.DST_COLOR,
gl.ONE_MINUS_DST_COLOR,
gl.SRC_ALPHA,
gl.ONE_MINUS_SRC_ALPHA,
gl.DST_ALPHA,
gl.ONE_MINUS_DST_ALPHA,
gl.CONSTANT_COLOR,
gl.ONE_MINUS_CONSTANT_COLOR,
gl.CONSTANT_ALPHA,
gl.ONE_MINUS_CONSTANT_ALPHA,
gl.SRC_ALPHA_SATURATE
];
var equations = [
gl.FUNC_ADD,
gl.FUNC_SUBTRACT,
gl.FUNC_REVERSE_SUBTRACT
];
var list = [
{ val: 0, text: 'gl.ZERO' },
{ val: 1, text: 'gl.ONE' },
{ val: 2, text: 'gl.SRC_COLOR' },
{ val: 3, text: 'gl.ONE_MINUS_SRC_COLOR' },
{ val: 4, text: 'gl.DST_COLOR' },
{ val: 5, text: 'gl.ONE_MINUS_DST_COLOR' },
{ val: 6, text: 'gl.SRC_ALPHA' },
{ val: 7, text: 'gl.ONE_MINUS_SRC_ALPHA' },
{ val: 8, text: 'gl.DST_ALPHA' },
{ val: 9, text: 'gl.ONE_MINUS_DST_ALPHA' },
{ val: 10, text: 'gl.CONSTANT_COLOR' },
{ val: 11, text: 'gl.ONE_MINUS_CONSTANT_COLOR' },
{ val: 12, text: 'gl.CONSTANT_ALPHA' },
{ val: 13, text: 'gl.ONE_MINUS_CONSTANT_ALPHA' },
{ val: 14, text: 'gl.SRC_ALPHA_SATURATE' }
];
var list2 = [
{ val: 0, text: 'gl.FUNC_ADD' },
{ val: 1, text: 'gl.FUNC_SUBTRACT' },
{ val: 2, text: 'gl.FUNC_REVERSE_SUBTRACT' }
];
var sfactor = gl.ONE;
var dfactor = gl.ZERO;
var equation = gl.FUNC_ADD;
var newMode = [ sfactor, dfactor ];
var renderer = this.sys.game.renderer;
var modeIndex = renderer.addBlendMode(newMode, equation);
this.add.image(400, 300, 'face');
this.add.image(400, 300, 'dst');
this.add.image(400, 300, 'src').setBlendMode(modeIndex);
// Create some select lists
var source = $('<select>').attr('id', 'source').appendTo('body');
$(list).each(function() {
source.append($("<option>").attr('value', this.val).text(this.text));
});
$(source).on('change', function () {
sfactor = consts[this.value];
newMode[0] = sfactor;
renderer.updateBlendMode(modeIndex, newMode, equation);
});
var dest = $('<select>').attr('id', 'dest').appendTo('body');
$(list).each(function() {
dest.append($("<option>").attr('value', this.val).text(this.text));
});
$(dest).on('change', function () {
dfactor = consts[this.value];
newMode[1] = dfactor;
renderer.updateBlendMode(modeIndex, newMode, equation);
});
var equ = $('<select>').attr('id', 'equ').appendTo('body');
$(list2).each(function() {
equ.append($("<option>").attr('value', this.val).text(this.text));
});
$(equ).on('change', function () {
equation = equations[this.value];
renderer.updateBlendMode(modeIndex, newMode, equation);
});
}
}
const config = {
type: Phaser.WEBGL,
width: 800,
height: 600,
parent: 'phaser-example',
scene: Example
};
const game = new Phaser.Game(config);
Подготовка и базовые понятия WebGL
Режим наложения в WebGL определяется тремя параметрами: фактор источника (sfactor), фактор назначения (dfactor) и уравнение смешивания (equation). Они указывают, как цвет рисуемого пикселя (источник) комбинируется с цветом пикселя, уже находящегося в буфере кадра (назначение).
Пример начинается с получения контекста WebGL и создания массивов, содержащих стандартные константы для факторов и уравнений. Эти константы импортируются из объекта gl, который представляет рендерер WebGL игры.
var gl = this.sys.game.renderer.gl;
var consts = [
gl.ZERO,
gl.ONE,
gl.SRC_COLOR,
// ... другие константы
];
var equations = [
gl.FUNC_ADD,
gl.FUNC_SUBTRACT,
gl.FUNC_REVERSE_SUBTRACT
];
Создание кастомного режима наложения
Phaser управляет режимами наложения через рендерер. Метод renderer.addBlendMode() регистрирует новый режим. Он принимает массив из двух элементов [sfactor, dfactor] и уравнение смешивания, возвращая индекс нового режима. Этот индекс затем используется в методе setBlendMode() для игровых объектов.
В примере изначально создается режим, где фактор источника — gl.ONE, а назначения — gl.ZERO. Это эквивалентно обычной отрисовке без смешивания (источник полностью заменяет назначение).
var sfactor = gl.ONE;
var dfactor = gl.ZERO;
var equation = gl.FUNC_ADD;
var newMode = [ sfactor, dfactor ];
var renderer = this.sys.game.renderer;
var modeIndex = renderer.addBlendMode(newMode, equation);
После создания режима, в сцену добавляются три изображения. Последнее изображение (src) применяет наш новый режим наложения.
this.add.image(400, 300, 'face');
this.add.image(400, 300, 'dst');
this.add.image(400, 300, 'src').setBlendMode(modeIndex);
Динамическое обновление параметров
Самая мощная часть примера — возможность изменять параметры режима наложения в реальном времени. Для этого используется метод renderer.updateBlendMode(). Он принимает индекс режима, обновленный массив факторов и уравнение.
В примере создаются три HTML-селекта (используется jQuery), которые позволяют выбрать фактор источника, фактор назначения и уравнение. При изменении значения в любом селекте, соответствующий параметр обновляется, и вызывается updateBlendMode. Это мгновенно применяет изменения к отображаемому изображению.
$(source).on('change', function () {
sfactor = consts[this.value];
newMode[0] = sfactor;
renderer.updateBlendMode(modeIndex, newMode, equation);
});
// Аналогично для dest и equ
Практическое применение и ограничения
Этот подход — прямое использование WebGL. Поэтому он работает **только** с рендерером Phaser.WEBGL. При использовании Phaser.CANVAS эти методы не будут доступны.
Такая техника полезна для: * Создания уникальных визуальных фильтров для спецэффектов (магия, искажения). * Реализации сложных систем освещения, где свечение комбинируется по нестандартным правилам. * Настройки точного контроля над прозрачностью и наложением слоев UI.
Важно помнить, что вы работаете с низкоуровневыми константами OpenGL. Для понимания результата часто нужна практика и эксперименты, так как визуальный итог зависит от выбранной пары факторов и уравнения.
Что попробовать дальше
Phaser 3 предоставляет прямой доступ к механизмам смешивания WebGL, позволяя выходить далеко за рамки предустановленных режимов наложения. Используя addBlendMode и updateBlendMode, вы можете создавать динамические и уникальные визуальные эффекты прямо во время выполнения игры.
**Идеи для экспериментов:**
1. Свяжите параметры смешивания с игровой логикой. Например, пусть фактор источника (sfactor) плавно меняется от gl.SRC_ALPHA к gl.ONE, создавая эффект нарастающего свечения при получении силы.
2. Попробуйте уравнение gl.FUNC_REVERSE_SUBTRACT в сочетании с разными факторами для создания эффектов "вычитания" цвета.
3. Создайте библиотеку из нескольких кастомных режимов для разных типов погодных эффектов (дождь, туман, жара).
