В Phaser 3 шейдеры реализуются через объект Pipeline и
позволяют создавать уникальные визуальные эффекты как для отдельных
объектов, так и для всей сцены. В основе лежит WebGL,
что обеспечивает высокую производительность и гибкость.
Шейдер может быть применён к спрайту, группе спрайтов или к камере. При этом различают два подхода: использование фрагментных шейдеров (fragment shader) для изменения цвета и текстуры, и вершинных шейдеров (vertex shader) для трансформации геометрии объектов.
Phaser 3 позволяет создавать свои пайплайны на основе
Phaser.Renderer.WebGL.Pipelines.SinglePipeline. Базовый
пример шейдера:
class MyShaderPipeline extends Phaser.Renderer.WebGL.Pipelines.SinglePipeline {
constructor(game) {
super({
game: game,
fragShader: `
precision mediump float;
uniform sampler2D uMainSampler;
varying vec2 outTexCoord;
void main() {
vec4 color = texture2D(uMainSampler, outTexCoord);
color.rg = color.rg * 0.5 + 0.5; // корректировка красного и зелёного каналов
gl_FragColor = color;
}`
});
}
}
После создания пайплайна его необходимо зарегистрировать в сцене:
this.renderer.addPipeline('MyShader', new MyShaderPipeline(this.game));
Чтобы применить шейдер к спрайту:
let sprite = this.add.sprite(400, 300, 'myTexture');
sprite.setPipeline('MyShader');
Особенности:
let pipeline = this.renderer.getPipeline('MyShader');
pipeline.setFloat1('time', this.time.now / 1000);
Шейдер, применённый к камере, воздействует на всю сцену, видимую через эту камеру. Это удобно для эффектов постобработки, таких как размытие, инверсия цветов или волны.
let camera = this.cameras.main;
camera.setRenderToTexture('MyShader');
При необходимости можно передавать в шейдер параметры камеры:
camera.setRenderToTexture({
pipeline: 'MyShader',
clear: true,
uniforms: {
time: 0
}
});
Динамическое обновление:
camera.pipeline.setFloat1('time', this.time.now / 1000);
Uniform-переменные позволяют управлять поведением шейдера из JavaScript. Обычно используют:
float — одиночное числоvec2, vec3, vec4 —
векторыsampler2D — текстурыПример управления волновым эффектом:
pipeline.setFloat1('amplitude', 0.05);
pipeline.setFloat1('frequency', 10.0);
В шейдере это применяется для смещения текстуры:
vec2 uv = outTexCoord;
uv.y += sin(uv.x * frequency + time) * amplitude;
gl_FragColor = texture2D(uMainSampler, uv);
Phaser позволяет использовать несколько шейдеров одновременно:
let rt = this.add.renderTexture(0, 0, 800, 600);
rt.draw(this.add.sprite(400, 300, 'myTexture'));
rt.setPipeline('MyShader');
Шейдеры часто используют время как uniform для создания анимации. В Phaser есть удобный источник времени:
this.time.addEvent({
loop: true,
callback: () => {
pipeline.setFloat1('time', this.time.now / 1000);
}
});
Так можно реализовать эффекты пульсации, волны, мерцания или цветовые переходы.
При применении шейдера важно учитывать прозрачность. Phaser сохраняет альфа-канал объектов:
vec4 color = texture2D(uMainSampler, outTexCoord);
color.rgb *= 0.5; // затемнение
gl_FragColor = vec4(color.rgb, color.a); // сохраняем прозрачность
Это позволяет совмещать шейдеры с наложением спрайтов и эффектами частиц.
Шейдеры в Phaser обеспечивают гибкий инструмент для создания уникальной визуальной атмосферы и интерактивных эффектов без существенной потери производительности. Их использование позволяет реализовать эффекты, которые сложно добиться стандартными средствами спрайтов и камер.