В системе визуализации CesiumJS материалы представляют собой уровень абстракции между геометрией (примитивами и сущностями сцены) и финальным фрагментным шейдером WebGL. Материал определяет, каким образом пиксели поверхности вычисляются на этапе растеризации: цвет, прозрачность, текстура, анимация, процедурные эффекты и любые комбинации этих параметров.
Архитектурно материал в CesiumJS представляет собой декларативное описание «fabric» (ткань), которое компилируется в GLSL-код фрагментного шейдера с набором унифицированных параметров (uniforms). Такой подход позволяет отделить описание внешнего вида от низкоуровневого WebGL-кода.
Базовая модель материала в CesiumJS строится вокруг объекта
Material, содержащего описание в формате fabric:
type — идентификатор материалаuniforms — параметры, передаваемые в шейдерsource — GLSL-фрагмент кода, определяющий
czm_materialСтруктура czm_material является стандартной точкой
взаимодействия с движком:
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;
}
czm_materialInput содержит данные о текущем фрагменте:
UV-координаты, позицию, нормали и дополнительные вычисленные
значения.
Создание нового типа материала выполняется через регистрацию:
import * as Cesium from "cesium";
Cesium.Material.StripeType = "StripeMaterial";
Cesium.Material.StripeSource = `
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
float stripe = step(0.5, fract(materialInput.st.s * 10.0));
vec3 color = mix(vec3(1.0), vec3(0.0, 0.6, 1.0), stripe);
material.diffuse = color;
material.alpha = 1.0;
return material;
}
`;
Cesium.Material._materialCache.addMaterial(Cesium.Material.StripeType, {
fabric: {
type: Cesium.Material.StripeType,
uniforms: {
repeat: 10.0
},
source: Cesium.Material.StripeSource
},
translucent: false
});
После регистрации материал становится доступен через
Material.fromType.
Материалы применяются через Appearance объектов:
const material = Cesium.Material.fromType("StripeMaterial", {
repeat: 20.0
});
const appearance = new Cesium.PerInstanceColorAppearance({
translucent: false
});
appearance.material = material;
Для геометрии:
const primitive = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.RectangleGeometry({
rectangle: Cesium.Rectangle.fromDegrees(-100, 30, -90, 40)
})
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
material: material
})
});
Основной входной параметр большинства материалов —
materialInput.st, где:
st.s — горизонтальная координата (U)st.t — вертикальная координата (V)Это позволяет строить процедурные текстуры без использования изображений:
float grid(vec2 st)
{
vec2 grid = fract(st * 20.0);
return step(0.95, grid.x) + step(0.95, grid.y);
}
Cesium автоматически предоставляет ряд встроенных uniform-переменных:
czm_frameNumberczm_frameTimeDeltaczm_timeПример анимированного материала:
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
float t = czm_frameNumber * 0.02;
float wave = sin(materialInput.st.s * 10.0 + t);
vec3 color = vec3(0.2, 0.6, 1.0) * (0.5 + 0.5 * wave);
material.diffuse = color;
material.alpha = 1.0;
return material;
}
Такая модель позволяет создавать эффекты воды, пульсации, бегущих полос и динамических градиентов.
Для сущностей (Entity API) используется
MaterialProperty, обеспечивающий реактивное поведение
материала во времени.
const entity = viewer.entities.add({
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(-120, 30, -100, 40),
material: new Cesium.ColorMaterialProperty(
Cesium.Color.BLUE.withAlpha(0.5)
)
}
});
Для пользовательской логики:
function PulseMaterialProperty() {
this.definitionChanged = new Cesium.Event();
}
PulseMaterialProperty.prototype.getType = function () {
return "StripeMaterial";
};
PulseMaterialProperty.prototype.getValue = function (time, result) {
result = result || {};
result.repeat = 10.0 + Math.sin(Date.now() * 0.001) * 5.0;
return result;
};
PulseMaterialProperty.prototype.isConstant = false;
Такой подход позволяет связывать материалы с временем и внешними данными (например, потоками сенсоров или API).
Материалы могут использовать текстуры через
sampler2D:
uniform sampler2D image;
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
vec4 color = texture2D(image, materialInput.st);
material.diffuse = color.rgb;
material.alpha = color.a;
return material;
}
JavaScript-часть:
Cesium.Material.fromType("ImageMaterial", {
image: "texture.png"
});
Для линий используется отдельный класс материалов через
PolylineMaterialAppearance.
const polyline = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.PolylineGeometry({
positions: Cesium.Cartesian3.fromDegreesArray([
-75, 35,
-125, 35
]),
width: 5
})
}),
appearance: new Cesium.PolylineMaterialAppearance({
material: Cesium.Material.fromType("PolylineGlow", {
glowPower: 0.3,
color: Cesium.Color.CYAN
})
})
});
Кастомные полилинейные материалы используют те же принципы GLSL, но учитывают особенности геометрии ленты.
Любой материал в CesiumJS компилируется в следующую логическую структуру:
czm_getMaterialdiffusealphaПример полной структуры:
uniform float speed;
czm_material czm_getMaterial(czm_materialInput materialInput)
{
czm_material material = czm_getDefaultMaterial(materialInput);
float value = sin(materialInput.st.t * 20.0 + czm_time * speed);
material.diffuse = vec3(value);
material.alpha = 1.0;
return material;
}
Uniforms связываются с JavaScript-объектом:
const material = Cesium.Material.fromType("CustomMaterial", {
speed: 2.0
});
Изменение значения uniforms в runtime приводит к немедленной перекомпиляции или обновлению шейдера в зависимости от типа материала.
Процедурные материалы часто используют шумовые функции:
float noise(vec2 st)
{
return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453);
}
Применение:
float n = noise(materialInput.st * 10.0);
material.diffuse = vec3(n);
Такие методы позволяют создавать облака, воду, дымовые и термические эффекты.
Материалы могут учитывать освещение сцены через нормали:
materialInput.normalECmaterialInput.positionECПример диффузного освещения:
vec3 lightDir = normalize(vec3(1.0, 1.0, 1.0));
float diffuse = max(dot(materialInput.normalEC, lightDir), 0.0);
material.diffuse *= diffuse;
Материалы в CesiumJS компилируются в отдельные WebGL программы. Это означает:
Оптимизация часто сводится к:
Материалы могут комбинироваться через смешивание цветов:
material.diffuse = mix(colorA, colorB, materialInput.st.s);
или через альфа-композицию:
material.alpha = baseAlpha * textureAlpha;
Такая модель используется для наложения нескольких эффектов: градиенты, шум + текстура, анимация + маска.
Процедурные материалы применяются для:
Каждый из этих сценариев опирается на одну и ту же архитектуру fabric + GLSL + uniforms, что делает систему масштабируемой и предсказуемой в поведении.