Babylon.js предоставляет мощный и гибкий интерфейс для работы с шейдерами, позволяя напрямую управлять атрибутами, uniform-переменными и текстурными сэмплерами. Эти механизмы являются основой для создания настраиваемой визуализации и сложной графики на WebGL.
Атрибуты (attributes) — это данные, которые передаются в вершинный
шейдер для каждой вершины. В Babylon.js стандартные атрибуты включают
позиции (position), нормали (normal),
координаты текстур (uv) и цвета вершин
(color). Они задаются через объект
VertexBuffer и привязываются к материалу или кастомному
шейдеру.
Пример определения атрибута при создании кастомного шейдера:
const shaderMaterial = new BABYLON.ShaderMaterial("shader", scene, {
vertex: "customVertex",
fragment: "customFragment",
}, {
attributes: ["position", "normal", "uv"],
uniforms: ["worldViewProjection"]
});
Ключевой момент: названия атрибутов должны точно совпадать с теми, что используются в GLSL-коде шейдера. Несовпадение приведёт к тому, что данные не будут переданы.
Uniform-переменные — это константы для всех вершин или пикселей в
рендере. Они не изменяются для каждой отдельной вершины, но могут
изменяться между кадрами. В Babylon.js uniform-переменные задаются через
объект ShaderMaterial или через функции
setFloat, setVector3, setMatrix и
т.д.
Пример передачи uniform-переменной в шейдер:
shaderMaterial.setFloat("time", performance.now() * 0.001);
shaderMaterial.setVector3("lightPosition", new BABYLON.Vector3(10, 20, 30));
shaderMaterial.setMatrix("worldViewProjection", scene.getTransformMatrix());
Uniform-переменные часто используются для передачи:
world,
view, projection,
worldViewProjection)lightPosition,
lightColor, lightIntensity)time,
deltaTime)Важно: uniform-переменные должны быть заранее
объявлены в шейдере. Babylon.js автоматически синхронизирует данные при
вызове методов set*, но если название не совпадает, данные
не будут переданы.
Sampler-переменные в GLSL позволяют шейдерам получать доступ к
текстурным данным. В Babylon.js текстуры передаются через
uniform-сэмплеры. Для этого используется класс Texture и
метод setTexture объекта ShaderMaterial.
Пример использования текстуры:
const diffuseTexture = new BABYLON.Texture("textures/wood.jpg", scene);
shaderMaterial.setTexture("diffuseSampler", diffuseTexture);
В шейдере GLSL текстура объявляется как
uniform sampler2D diffuseSampler; и используется с помощью
функции texture2D или texture в новых версиях
GLSL:
vec4 color = texture2D(diffuseSampler, uv);
Особенности работы с текстурами в Babylon.js:
Texture и его методам (update,
readPixels, dispose).Комплексное использование этих трёх типов данных позволяет создавать
гибкие эффекты. Например, можно передать положение вершины через атрибут
position, использовать uniform time для
анимации смещения и текстуру через sampler для наложения цвета:
attribute vec3 position;
attribute vec2 uv;
uniform mat4 worldViewProjection;
uniform float time;
uniform sampler2D diffuseSampler;
void main() {
vec3 animatedPos = position + vec3(0.0, sin(time + position.x), 0.0);
gl_Position = worldViewProjection * vec4(animatedPos, 1.0);
}
Фрагментный шейдер:
varying vec2 vUV;
uniform sampler2D diffuseSampler;
void main() {
gl_FragColor = texture2D(diffuseSampler, vUV);
}
В Babylon.js для привязки переменных:
shaderMaterial.setFloat("time", performance.now() * 0.001);
shaderMaterial.setTexture("diffuseSampler", diffuseTexture);
Babylon.js позволяет обновлять uniform и атрибуты каждый кадр через функцию рендера:
scene.registerBeforeRender(() => {
shaderMaterial.setFloat("time", performance.now() * 0.001);
});
Для атрибутов вершин динамическое обновление требует использования
VertexBuffer с флагом Dynamic:
const positions = new Float32Array([/* координаты вершин */]);
const vertexBuffer = new BABYLON.VertexBuffer(engine, positions, BABYLON.VertexBuffer.PositionKind, true, false, 3);
Это особенно полезно для анимации мешей, деформации и эффектов частиц.
ShaderMaterial позволяет объединять все
три подхода в единый материал.Эти механизмы обеспечивают максимальную гибкость при создании пользовательских шейдеров и эффектов в Babylon.js, позволяя управлять каждой вершиной и пикселем с помощью JavaScript.