Процедурные материалы (Procedural Materials) в CesiumJS представляют собой материалы, внешний вид которых формируется математическими вычислениями в шейдерах, а не готовыми текстурами. Такой подход позволяет создавать динамические визуальные эффекты, изменяющиеся во времени, масштабируемые без потери качества и не требующие хранения больших графических ресурсов.
Процедурные материалы активно используются для отображения:
В основе системы лежит класс Material, который
определяет способ вычисления цвета каждого пикселя поверхности.
Материал применяется к различным графическим примитивам:
Пример назначения материала объекту:
viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([
30, 50,
31, 50,
31, 51,
30, 51
]),
material: Cesium.Color.BLUE
}
});
В данном случае используется простейший цветовой материал.
Фактически Cesium автоматически преобразует цвет в внутренний объект материала.
Основным элементом системы является:
Cesium.Material
Создание материала вручную:
const material = new Cesium.Material({
fabric: {
type: 'Color',
uniforms: {
color: Cesium.Color.RED
}
}
});
Структура fabric описывает материал декларативно.
Основные компоненты:
| Элемент | Назначение |
|---|---|
| type | Имя материала |
| uniforms | Параметры материала |
| source | GLSL-код |
| materials | Вложенные материалы |
| components | Отдельные каналы цвета |
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 содержит набор встроенных материалов.
Простейший материал однотонной заливки.
material: Cesium.Color.YELLOW
Или:
material: new Cesium.ColorMaterialProperty(
Cesium.Color.YELLOW
)
Шахматный узор.
material: new Cesium.CheckerboardMaterialProperty({
evenColor: Cesium.Color.WHITE,
oddColor: Cesium.Color.BLACK,
repeat: new Cesium.Cartesian2(8, 8)
})
Результат напоминает шахматную доску.
Материал координатной сетки.
material: new Cesium.GridMaterialProperty({
color: Cesium.Color.LIME,
cellAlpha: 0.2,
lineCount: new Cesium.Cartesian2(10, 10)
})
Применяется для:
Полосатый материал.
material: new Cesium.StripeMaterialProperty({
evenColor: Cesium.Color.BLUE,
oddColor: Cesium.Color.WHITE,
repeat: 20
})
Может использоваться для визуализации:
Материал на основе изображения.
material: new Cesium.ImageMaterialProperty({
image: 'texture.png'
})
Хотя данный материал использует текстуру, он может комбинироваться с процедурными эффектами.
Один из наиболее сложных встроенных материалов.
Применяется к водным поверхностям.
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 | Амплитуда |
Создает эффект свечения линий.
polyline: {
positions: positions,
width: 10,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.3,
color: Cesium.Color.CYAN
})
}
Используется для отображения:
Линия с контуром.
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;
}
`
}
});
Здесь яркость вычисляется функцией синуса.
Параметры материала передаются через 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(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 и интегрировать их непосредственно в трехмерную сцену без необходимости использования заранее подготовленных текстур.