В PixiJS шейдеры реализуются через объекты
PIXI.Shader и PIXI.Program. Uniform-переменные
служат для передачи данных с CPU на GPU и обеспечивают динамическую
настройку поведения шейдера без его перекомпиляции. Их использование
критически важно для создания эффектов, изменяющихся в реальном времени:
анимаций, деформаций, цветовых фильтров и текстурных трансформаций.
Uniform-переменные объявляются в GLSL коде шейдера в верхней части программы:
// Vertex shader
uniform mat3 u_transform;
uniform float u_time;
// Fragment shader
uniform vec4 u_color;
uniform sampler2D u_texture;
float, int — скаляры;vec2, vec3, vec4 —
векторы;mat3, mat4 — матрицы;sampler2D — текстура.Важно, что uniform-переменные сохраняют своё значение между вызовами рендеринга, пока явно не изменены через JavaScript.
В PixiJS шейдер создаётся через PIXI.Shader с указанием
программы и объекта uniform-переменных:
const vertexSrc = `
precision mediump float;
attribute vec2 aVertexPosition;
uniform mat3 u_transform;
void main() {
vec3 pos = u_transform * vec3(aVertexPosition, 1.0);
gl_Position = vec4(pos.xy, 0.0, 1.0);
}
`;
const fragmentSrc = `
precision mediump float;
uniform vec4 u_color;
void main() {
gl_FragColor = u_color;
}
`;
const uniforms = {
u_color: new Float32Array([1.0, 0.0, 0.0, 1.0]),
u_transform: new Float32Array([1,0,0,0,1,0,0,0,1])
};
const shader = PIXI.Shader.from(vertexSrc, fragmentSrc, uniforms);
Здесь объект uniforms связывает имена uniform-переменных
с их значениями. Использование Float32Array обеспечивает
корректную передачу данных на GPU.
Uniform-переменные можно изменять динамически, что позволяет создавать анимации и интерактивные эффекты:
app.ticker.add((delta) => {
shader.uniforms.u_time = performance.now() / 1000;
shader.uniforms.u_color = new Float32Array([
Math.sin(performance.now() / 500) * 0.5 + 0.5,
0.0,
0.0,
1.0
]);
});
performance.now() используется для получения текущего
времени в миллисекундах.Текстуры в uniform-переменные передаются через
PIXI.Texture. В GLSL они объявляются как
sampler2D:
const texture = PIXI.Texture.from('image.png');
const uniforms = {
u_texture: texture
};
const fragmentSrc = `
precision mediump float;
uniform sampler2D u_texture;
varying vec2 vTextureCoord;
void main() {
gl_FragColor = texture2D(u_texture, vTextureCoord);
}
`;
const shader = PIXI.Shader.from(vertexSrc, fragmentSrc, uniforms);
Внутри фрагментного шейдера
texture2D(u_texture, vTextureCoord) возвращает цвет
пикселя, соответствующий координате текстуры.
Uniform-переменные работают независимо от атрибутов, которые описывают вершины:
attribute) изменяются для
каждой вершины.Пример комбинирования:
attribute vec2 aVertexPosition;
uniform vec2 u_offset;
void main() {
gl_Position = vec4(aVertexPosition + u_offset, 0.0, 1.0);
}
В JavaScript можно сдвигать фигуру, изменяя u_offset без
модификации вершин:
shader.uniforms.u_offset = new Float32Array([Math.sin(time), 0.0]);
Float32Array или Int32Array
для массивов чисел.Float32Array размером 9
(mat3) или 16 (mat4).[r, g, b, a].PIXI.Texture
напрямую.Можно создавать uniform-переменные в цикле для генерации эффектов с множеством источников:
const numLights = 4;
const uniforms = {};
for (let i = 0; i < numLights; i++) {
uniforms[`u_lightPos${i}`] = new Float32Array([Math.random(), Math.random()]);
uniforms[`u_lightColor${i}`] = new Float32Array([1.0, 1.0, 1.0]);
}
Это позволяет гибко управлять несколькими источниками света или эффектами частиц.
Передача uniform-переменных в PixiJS — основа взаимодействия CPU и GPU, обеспечивающая высокую производительность и гибкость визуальных эффектов. Правильная организация uniform-данных позволяет создавать сложные шейдерные эффекты с минимальными затратами ресурсов и максимальной повторной используемостью шейдеров.