ShaderStore: хранение шейдеров по имени

Babylon.js предоставляет мощный механизм работы с шейдерами через объект ShaderStore, который позволяет сохранять и управлять шейдерами по уникальным именам. Это критически важно для создания сложных визуальных эффектов, переиспользования кода и упрощения интеграции пользовательских шейдеров в сцены.

Основные концепции ShaderStore

ShaderStore — это глобальный контейнер для хранения текстов шейдеров. Он используется для Vertex и Fragment шейдеров, а также для их комбинаций в виде Effect. Шейдеры хранятся как строки, доступные по имени, что позволяет обращаться к ним из различных компонентов Babylon.js.

Структура хранения выглядит следующим образом:

ShaderStore.ShadersStore = {
    [shaderName + "VertexShader"]: "vertex shader code",
    [shaderName + "FragmentShader"]: "fragment shader code"
};
  • shaderName — уникальное имя шейдера.
  • VertexShader и FragmentShader — суффиксы, обозначающие тип шейдера.
  • shader code — GLSL-код шейдера, который будет использован движком.

Добавление пользовательских шейдеров

Создание собственного шейдера начинается с написания GLSL-кода для вершинного и фрагментного шейдеров. После этого шейдеры регистрируются в ShaderStore:

import { ShaderStore } from "@babylonjs/core/Engines/shaderStore";

ShaderStore.ShadersStore["customVertexShader"] = `
    precision highp float;
    attribute vec3 position;
    uniform mat4 worldViewProjection;
    void main(void) {
        gl_Position = worldViewProjection * vec4(position, 1.0);
    }
`;

ShaderStore.ShadersStore["customFragmentShader"] = `
    precision highp float;
    uniform vec4 color;
    void main(void) {
        gl_FragColor = color;
    }
`;

Особенности:

  • Ключи в ShaderStore чувствительны к регистру и суффиксам.
  • GLSL-код должен быть полностью валиден, иначе эффекты не создадутся.
  • ShaderStore доступен глобально, что позволяет переиспользовать шейдеры в разных сценах.

Использование шейдеров через Effect

После регистрации шейдера в ShaderStore его можно применять через объект Effect:

import { Effect } from "@babylonjs/core/Materials/effect";

const effect = new Effect(
    "customEffect",
    ["customVertexShader", "customFragmentShader"],
    ["worldViewProjection", "color"],
    ["position"],
    scene.getEngine()
);

effect.setFloat4("color", 1.0, 0.0, 0.0, 1.0);
  • Первый аргумент — уникальное имя Effect.
  • Второй — массив имен шейдеров для вершинного и фрагментного этапов.
  • Третий — список uniform-переменных.
  • Четвёртый — список атрибутов.
  • Пятый — движок, на котором создается Effect.

Effect автоматически подтягивает GLSL-код из ShaderStore по указанным именам.

Применение шейдеров к материалам

Для интеграции пользовательских шейдеров в материалы Babylon.js используют ShaderMaterial:

import { ShaderMaterial } from "@babylonjs/core/Materials/shaderMaterial";

const shaderMaterial = new ShaderMaterial(
    "customShaderMaterial",
    scene,
    {
        vertex: "customVertexShader",
        fragment: "customFragmentShader",
    },
    {
        attributes: ["position"],
        uniforms: ["worldViewProjection", "color"]
    }
);

shaderMaterial.setColor4("color", new BABYLON.Color4(0, 1, 0, 1));
mesh.material = shaderMaterial;
  • Атрибуты и uniform-переменные должны совпадать с объявленными в GLSL.
  • ShaderMaterial позволяет полностью контролировать визуальный результат, заменяя стандартные материалы.

Динамическое обновление шейдеров

ShaderStore поддерживает возможность динамического обновления шейдеров во время выполнения сцены. Например, можно подгружать новые версии шейдеров без перезагрузки страницы:

ShaderStore.ShadersStore["customFragmentShader"] = `
    precision highp float;
    uniform vec4 color;
    void main(void) {
        gl_FragColor = vec4(color.rgb * 0.5, color.a);
    }
`;

effect._bind(); // Перепривязка к обновленному шейдеру

Это особенно полезно для реализации эффектов смены визуального стиля, постобработки или динамического освещения.

Преимущества использования ShaderStore

  • Централизованное хранение шейдеров, что упрощает поддержку проекта.
  • Переиспользование шейдеров между различными Effect и ShaderMaterial.
  • Динамическое обновление, позволяющее создавать интерактивные визуальные эффекты.
  • Упрощение интеграции сторонних GLSL-библиотек, подключаемых через строковый код.

ShaderStore является фундаментальной частью архитектуры материалов в Babylon.js и обеспечивает гибкий контроль над визуальными эффектами сцены. Правильное использование этого механизма позволяет создавать производительные, масштабируемые и настраиваемые графические решения.