Процедурные текстуры через ProceduralTexture

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

Создание ProceduralTexture

Для создания процедурной текстуры необходимо использовать конструктор класса BABYLON.ProceduralTexture:

const proceduralTexture = new BABYLON.ProceduralTexture(
    "proceduralTexture", // имя текстуры
    512,                 // размер текстуры в пикселях (ширина = высота)
    "customShader",      // имя шейдера, определяемого в папке shaders
    scene                 // сцена, к которой привязана текстура
);

Параметры:

  • name — уникальное имя текстуры.
  • size — разрешение текстуры, рекомендуется степени двойки (256, 512, 1024).
  • fragment — имя файла фрагментного шейдера (GLSL), который будет использоваться для генерации пикселей.
  • scene — объект сцены Babylon.js, в которой создаётся текстура.

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

Настройка шейдера

Фрагментный шейдер (GLSL) — основа процедурной текстуры. Он получает координаты пикселя и возвращает цвет в формате RGBA. Babylon.js передает в шейдер набор стандартных uniform-переменных:

  • time — время, прошедшее с начала рендеринга, используется для анимации.
  • resolution — вектор размеров текстуры.
  • uv — координаты пикселя в диапазоне [0,1].

Пример простого шейдера:

precision highp float;

varying vec2 vUV;
uniform float time;

void main(void) {
    vec2 uv = vUV;
    float value = 0.5 + 0.5 * sin(uv.x * 10.0 + time);
    gl_FragColor = vec4(vec3(value), 1.0);
}

Этот шейдер создает анимированную полосатую текстуру, где значение цвета изменяется во времени.

Использование текстуры в материале

После создания процедурной текстуры ее можно назначить на любой материал:

const material = new BABYLON.StandardMaterial("mat", scene);
material.diffuseTexture = proceduralTexture;
mesh.material = material;

Важно учитывать, что процедурная текстура может использоваться не только как диффузная (diffuseTexture), но и для нормалей (bumpTexture), отражений (reflectionTexture) или эмиссии (emissiveTexture), расширяя визуальные возможности.

Передача пользовательских параметров в шейдер

Для динамических эффектов часто требуется передавать собственные переменные в шейдер. Babylon.js предоставляет методы setFloat, setVector3, setColor3 и другие:

proceduralTexture.setFloat("intensity", 0.8);
proceduralTexture.setColor3("customColor", new BABYLON.Color3(1, 0, 0));

В шейдере их можно использовать через uniform-переменные:

uniform float intensity;
uniform vec3 customColor;

void main(void) {
    vec3 color = customColor * intensity;
    gl_FragColor = vec4(color, 1.0);
}

Анимация текстур

ProceduralTexture интегрирована с игровым циклом Babylon.js, поэтому обновление времени и других параметров можно производить автоматически. Для этого используется метод update:

scene.registerBeforeRender(() => {
    proceduralTexture.setFloat("time", performance.now() * 0.001);
});

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

Применение шумов и фильтров

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

  • Perlin Noise — плавные случайные шумы.
  • Simplex Noise — улучшенная версия Perlin с меньшей артефактностью.
  • Fractal Noise — комбинация шумов разных частот для создания органичных текстур.

Пример применения Perlin Noise в шейдере:

float perlinNoise(vec2 uv);

void main(void) {
    float n = perlinNoise(vUV * 5.0 + time * 0.1);
    gl_FragColor = vec4(vec3(n), 1.0);
}

Использование шумов позволяет моделировать текстуры камня, облаков, воды и огня с минимальными затратами памяти.

Интеграция с постобработкой

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

Советы по оптимизации

  • Выбирать минимально необходимое разрешение текстуры для экономии памяти.
  • Ограничивать частоту обновления шейдера, если анимация не критична.
  • Использовать встроенные функции Babylon.js для генерации шумов вместо сложных вычислений в GLSL.
  • Компилировать и тестировать шейдер на целевых устройствах для предотвращения падений производительности.

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