В CesiumJS система материалов построена вокруг декларативного описания внешнего вида геометрии через объектную модель, называемую Fabric. Fabric представляет собой JSON-описание материала, которое интерпретируется движком и транслируется в GLSL-шейдеры. Такой подход позволяет описывать визуальные эффекты без прямого ручного управления низкоуровневым WebGL-кодом, сохраняя при этом возможность тонкой кастомизации.
Fabric служит промежуточным слоем между JavaScript-логикой приложения и GPU-шейдерами. Он определяет структуру материала, входные параметры (uniforms), вспомогательные функции и фрагменты шейдерного кода, которые Cesium объединяет в итоговый материал.
Fabric описывается как JavaScript-объект, который может быть сериализован в JSON. Базовая структура включает несколько ключевых секций:
type — тип материалаuniforms — входные параметры шейдераsource — GLSL-фрагмент материалаcomponents,
translucent)Простейший пример Fabric:
const fabric = {
type: 'Color',
uniforms: {
color: Cesium.Color.RED
},
source: `
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
material.diffuse = color.rgb;
material.alpha = color.a;
return material;
}
`
};
Этот объект описывает материал, который окрашивает поверхность в заданный цвет.
Uniforms представляют собой динамические параметры, передаваемые из JavaScript в GLSL. Cesium автоматически синхронизирует их между CPU и GPU.
Основные особенности uniforms:
Пример использования:
uniforms: {
speed: 10.0,
frequency: 2.0,
color: Cesium.Color.BLUE
}
В шейдере:
uniform float speed;
uniform float frequency;
uniform vec4 color;
Uniforms позволяют создавать анимированные и параметрические материалы без изменения GLSL-кода.
Центральной частью Fabric является строка source,
содержащая GLSL-код. Cesium интегрирует этот код в общий пайплайн
материалов.
Каждый материал обязан возвращать структуру
czm_material, которая описывает:
diffuse — базовый цветalpha — прозрачностьemission — самосвечениеspecular — отражениеСтандартный шаблон:
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
// модификация свойств материала
material.diffuse = vec3(1.0, 0.0, 0.0);
material.alpha = 1.0;
return material;
}
Fabric позволяет внедрять пользовательскую логику вычисления цвета, шума, градиентов и процедурных текстур.
CesiumJS предоставляет набор стандартных Fabric-материалов, реализованных через ту же систему:
Каждый из них является декларацией Fabric-объекта с предопределённой логикой.
ColorMaterial задаёт однородную заливку поверхности.
const material = new Cesium.ColorMaterialProperty(
Cesium.Color.ORANGE
);
Внутри Fabric это сводится к передаче одного uniform
color, который используется для заполнения
diffuse.
ImageMaterial позволяет накладывать текстуру на геометрию.
Fabric-структура включает:
image — URL или текстураrepeat — повторение текстурыcolor — модификатор цветаПример:
const fabric = {
type: 'Image',
uniforms: {
image: 'texture.png',
repeat: new Cesium.Cartesian2(2.0, 2.0)
}
};
В GLSL текстура выборки выполняется через texture2D, а
координаты UV интерполируются из геометрии.
StripeMaterial и CheckerboardMaterial демонстрируют процедурный подход Fabric. Они не используют внешние текстуры, а вычисляют цвет на основе координат.
StripeMaterial:
CheckerboardMaterial:
mod() и
целочисленные операцииФрагмент логики:
float x = floor(st.s * stripes);
float y = floor(st.t * stripes);
float pattern = mod(x + y, 2.0);
Polyline материалы являются отдельной категорией Fabric, оптимизированной для линий.
Создаёт эффект свечения вдоль линии:
glowPowerСочетает основной цвет и обводку:
color — основной цветoutlineColor — цвет контураoutlineWidth — толщинаFabric для линий учитывает экранную координатную систему, а не только мировые координаты, что позволяет сохранять постоянную толщину при масштабировании камеры.
Cesium не использует Fabric напрямую в шейдере. Перед выполнением происходит этап компоновки:
Fabric может включать вспомогательные функции:
source: `
float noise(vec2 st)
{
return fract(sin(dot(st, vec2(12.9898,78.233))) * 43758.5453);
}
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
float n = noise(materialInput.st);
material.diffuse = vec3(n);
return material;
}
`
Cesium вставляет такие функции в общий namespace шейдера.
Fabric поддерживает композицию логики через дополнительные секции:
functions — вспомогательные GLSL-функцииcomponents — разбиение материала на частиtranslucent — управление прозрачностьюПример:
const fabric = {
uniforms: {
amplitude: 1.0
},
functions: `
float wave(float x) {
return sin(x);
}
`,
source: `
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
float w = wave(materialInput.st.s * 10.0);
material.diffuse = vec3(w);
return material;
}
`
};
Свойство translucent управляет режимом прозрачности:
true — материал участвует в alpha-blendingfalse — отрисовка как непрозрачного объектаПример:
translucent: function(material) {
return material.uniforms.alpha < 1.0;
}
Fabric-материалы в Cesium проходят несколько этапов жизни:
Материалы могут быть реактивными: изменение uniform автоматически приводит к пересборке или обновлению shader state.
Fabric предоставляет высокий уровень абстракции, но накладывает ограничения:
Оптимизация обычно достигается через:
Создание собственного материала сводится к определению Fabric-объекта с кастомным GLSL:
const customMaterial = new Cesium.Material({
fabric: {
type: 'CustomWave',
uniforms: {
time: 0.0
},
source: `
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
float wave = sin(materialInput.st.s * 10.0 + time);
material.diffuse = vec3(0.0, wave, 1.0);
return material;
}
`
}
});
Такой подход позволяет интегрировать процедурные эффекты, анимации и визуальные симуляции непосредственно в рендеринг Cesium без изменения ядра движка.