Процедурные материалы

Процедурные материалы (Procedural Materials) в CesiumJS представляют собой материалы, внешний вид которых формируется математическими вычислениями в шейдерах, а не готовыми текстурами. Такой подход позволяет создавать динамические визуальные эффекты, изменяющиеся во времени, масштабируемые без потери качества и не требующие хранения больших графических ресурсов.

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

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

В основе системы лежит класс Material, который определяет способ вычисления цвета каждого пикселя поверхности.


Архитектура материалов в CesiumJS

Материал применяется к различным графическим примитивам:

  • полигонам;
  • эллипсам;
  • прямоугольникам;
  • коридорам;
  • стенам;
  • цилиндрам;
  • пользовательской геометрии.

Пример назначения материала объекту:

viewer.entities.add({
    polygon: {
        hierarchy: Cesium.Cartesian3.fromDegreesArray([
            30, 50,
            31, 50,
            31, 51,
            30, 51
        ]),
        material: Cesium.Color.BLUE
    }
});

В данном случае используется простейший цветовой материал.

Фактически Cesium автоматически преобразует цвет в внутренний объект материала.


Класс Material

Основным элементом системы является:

Cesium.Material

Создание материала вручную:

const material = new Cesium.Material({
    fabric: {
        type: 'Color',
        uniforms: {
            color: Cesium.Color.RED
        }
    }
});

Структура fabric описывает материал декларативно.

Основные компоненты:

Элемент Назначение
type Имя материала
uniforms Параметры материала
source GLSL-код
materials Вложенные материалы
components Отдельные каналы цвета

Система Fabric

Fabric представляет собой специальный формат описания материалов в CesiumJS.

Общая структура:

const material = new Cesium.Material({
    fabric: {
        type: 'MyMaterial',

        uniforms: {
            color: Cesium.Color.CYAN,
            speed: 1.0
        },

        source: `
            czm_material czm_getMaterial(
                czm_materialInput materialInput)
            {
                czm_material material =
                    czm_getDefaultMaterial(materialInput);

                material.diffuse = color.rgb;
                material.alpha = color.a;

                return material;
            }
        `
    }
});

Fabric скрывает сложность работы с WebGL и позволяет создавать материалы на более высоком уровне абстракции.


Готовые процедурные материалы

Cesium содержит набор встроенных материалов.

Color

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

material: Cesium.Color.YELLOW

Или:

material: new Cesium.ColorMaterialProperty(
    Cesium.Color.YELLOW
)

Checkerboard

Шахматный узор.

material: new Cesium.CheckerboardMaterialProperty({
    evenColor: Cesium.Color.WHITE,
    oddColor: Cesium.Color.BLACK,
    repeat: new Cesium.Cartesian2(8, 8)
})

Результат напоминает шахматную доску.


Grid

Материал координатной сетки.

material: new Cesium.GridMaterialProperty({
    color: Cesium.Color.LIME,
    cellAlpha: 0.2,
    lineCount: new Cesium.Cartesian2(10, 10)
})

Применяется для:

  • отладки геометрии;
  • отображения зон;
  • технических карт;
  • инженерных моделей.

Stripe

Полосатый материал.

material: new Cesium.StripeMaterialProperty({
    evenColor: Cesium.Color.BLUE,
    oddColor: Cesium.Color.WHITE,
    repeat: 20
})

Может использоваться для визуализации:

  • коридоров;
  • транспортных маршрутов;
  • запрещённых зон.

Image

Материал на основе изображения.

material: new Cesium.ImageMaterialProperty({
    image: 'texture.png'
})

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


Материал Water

Один из наиболее сложных встроенных материалов.

Применяется к водным поверхностям.

const water = Cesium.Material.fromType('Water');

Настройка параметров:

const water = Cesium.Material.fromType('Water');

water.uniforms.baseWaterColor =
    Cesium.Color.DEEPSKYBLUE;

water.uniforms.blendColor =
    Cesium.Color.NAVY;

water.uniforms.frequency = 1000.0;
water.uniforms.animationSpeed = 0.01;
water.uniforms.amplitude = 10.0;

Основные параметры:

Параметр Назначение
baseWaterColor Основной цвет
blendColor Дополнительный оттенок
frequency Частота волн
animationSpeed Скорость движения
amplitude Амплитуда

Материал PolylineGlow

Создает эффект свечения линий.

polyline: {
    positions: positions,
    width: 10,
    material: new Cesium.PolylineGlowMaterialProperty({
        glowPower: 0.3,
        color: Cesium.Color.CYAN
    })
}

Используется для отображения:

  • маршрутов;
  • кабельных трасс;
  • потоков данных;
  • энергетических линий.

Материал PolylineOutline

Линия с контуром.

material: new Cesium.PolylineOutlineMaterialProperty({
    color: Cesium.Color.YELLOW,
    outlineColor: Cesium.Color.BLACK,
    outlineWidth: 2
})

Позволяет значительно повысить читаемость объектов на сложном фоне.


Создание пользовательского процедурного материала

Основное преимущество Cesium заключается в возможности создавать собственные материалы.

Пример простого пользовательского материала:

const material = new Cesium.Material({
    fabric: {
        type: 'PulseMaterial',

        uniforms: {
            color: Cesium.Color.RED,
            time: 0.0
        },

        source: `
            czm_material czm_getMaterial(
                czm_materialInput materialInput)
            {
                czm_material material =
                    czm_getDefaultMaterial(materialInput);

                float pulse =
                    abs(sin(time));

                material.diffuse =
                    color.rgb * pulse;

                material.alpha = pulse;

                return material;
            }
        `
    }
});

Здесь яркость вычисляется функцией синуса.


Uniform-переменные

Параметры материала передаются через uniforms.

Пример:

uniforms: {
    color: Cesium.Color.GREEN,
    speed: 1.5,
    radius: 50.0
}

Доступ внутри GLSL:

color
speed
radius

Типичные данные:

Тип Назначение
float Числа
vec2 Двумерные координаты
vec3 Векторы
vec4 Цвета
sampler2D Текстуры

Использование времени в материалах

Наиболее распространённый сценарий — создание анимации.

Регулярное обновление параметра:

viewer.scene.preRender.addEventListener(function() {
    material.uniforms.time += 0.02;
});

В шейдере:

float value = sin(time);

Такой подход позволяет реализовать:

  • мигание;
  • пульсацию;
  • волны;
  • вращение;
  • сканирование.

Работа с координатами материала

Материалы получают специальные текстурные координаты.

materialInput.st

Где:

s → горизонтальная координата
t → вертикальная координата

Пример:

vec2 st = materialInput.st;

Использование:

material.diffuse =
    vec3(st.x, st.y, 1.0);

В результате появляется цветовой градиент.


Линейный градиент

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

source: `
    czm_material czm_getMaterial(
        czm_materialInput materialInput)
    {
        czm_material material =
            czm_getDefaultMaterial(materialInput);

        vec2 st = materialInput.st;

        material.diffuse =
            vec3(st.x, 0.0, 1.0 - st.x);

        material.alpha = 1.0;

        return material;
    }
`

По мере движения по оси X цвет плавно меняется.


Кольцевой эффект

Эффект концентрических колец.

vec2 st = materialInput.st;

float dist =
    distance(st, vec2(0.5));

float ring =
    step(0.2, dist) -
    step(0.25, dist);

Полученное значение используется для управления яркостью.

material.diffuse =
    vec3(ring);

Подобные эффекты применяются для радаров и датчиков.


Эффект сканирующей волны

Часто используется в геоинформационных системах.

float wave =
    fract(time - dist * 3.0);

wave = smoothstep(
    0.0,
    0.2,
    wave
);

Результат:

material.alpha = wave;

Создается визуальная волна, распространяющаяся от центра.


Использование smoothstep

Функция:

smoothstep(min, max, value)

Обеспечивает плавный переход между значениями.

Пример:

float edge =
    smoothstep(
        0.3,
        0.35,
        dist
    );

Без неё границы выглядят резко:

step(...)

С ней переход становится плавным.


Комбинирование материалов

Fabric позволяет создавать составные материалы.

Пример структуры:

fabric: {
    materials: {
        first: {
            type: 'Color'
        },
        second: {
            type: 'Grid'
        }
    }
}

После чего результаты объединяются в одном шейдере.

Это позволяет одновременно использовать:

  • текстуры;
  • сетки;
  • анимацию;
  • градиенты;
  • процедурные эффекты.

Работа с компонентами материала

Вместо полного GLSL-шейдера можно переопределять отдельные компоненты.

Пример:

fabric: {
    uniforms: {
        color: Cesium.Color.CYAN
    },

    components: {
        diffuse: 'color.rgb',
        alpha: 'color.a'
    }
}

Подход удобен для небольших визуальных модификаций.


Оптимизация процедурных материалов

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

Практические рекомендации:

Минимизировать количество тригонометрических функций

Плохо:

sin(...)
cos(...)
tan(...)

Хорошо:

step(...)
smoothstep(...)

Сокращать число условий

Нежелательно:

if(...)
{
    ...
}

Предпочтительно:

mix(...)

или

step(...)

Избегать большого числа текстурных выборок

Каждый вызов:

texture(...)

увеличивает нагрузку на GPU.


Использовать Uniform вместо постоянной генерации данных

Плохо:

complexCalculation(...)

для каждого пикселя.

Лучше вычислить значение на стороне JavaScript и передать через:

uniforms

Типичные сценарии применения

Геоинформационные системы

  • зоны покрытия связи;
  • радиолокационные станции;
  • области мониторинга;
  • карты плотности данных.

Транспортные системы

  • анимированные маршруты;
  • направления движения;
  • выделение дорог.

Военные симуляторы

  • сканирование территории;
  • энергетические барьеры;
  • визуализация обнаружения целей.

Системы мониторинга

  • тепловые карты;
  • активные сенсоры;
  • динамические предупреждения.

Научная визуализация

  • распределение параметров среды;
  • поля измерений;
  • пространственные модели процессов.

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