Одним из наиболее прямых способов получения монохромного изображения сцены является управление параметрами слоя изображений (ImageryLayer). Каждый слой в CesiumJS может иметь настройки цветокоррекции, влияющие на итоговый рендер тайлов подложки.
Ключевой механизм — модификация насыщенности через HSV/HSB-подобные параметры, а также использование цветового смешивания.
Основная идея заключается в обнулении насыщенности:
Пример настройки слоя:
const viewer = new Cesium.Viewer("cesiumContainer");
const layer = viewer.imageryLayers.addImageryProvider(
new Cesium.OpenStreetMapImageryProvider({
url: "https://tile.openstreetmap.org/"
})
);
layer.saturation = 0.0;
layer.brightness = 1.0;
layer.contrast = 1.0;
При saturation = 0 сцена визуально превращается в градации серого, сохраняя структуру освещения и контуры объектов.
Cesium предоставляет механизм смешивания цвета слоя с глобальным
освещением сцены через ColorBlendMode.
Доступные режимы:
Для получения монохромного эффекта часто используется комбинация
MIX и уменьшенной насыщенности.
layer.colorBlendMode = Cesium.ColorBlendMode.MIX;
layer.colorBlendAmount = 0.7;
Этот подход полезен, когда требуется частичное обесцвечивание, сохраняя визуальную дифференциацию объектов.
Более универсальный метод — использование постобработки. В CesiumJS
сцена может быть изменена на уровне финального кадра через
PostProcessStage.
Наиболее распространённый вариант — применение матрицы преобразования цвета.
Классическая формула яркости:
Эта модель соответствует восприятию человеческого глаза.
Реализация через uniform-матрицу:
const grayscaleMatrix = [
0.2126, 0.2126, 0.2126, 0.0,
0.7152, 0.7152, 0.7152, 0.0,
0.0722, 0.0722, 0.0722, 0.0,
0, 0, 0, 1.0
];
const stage = new Cesium.PostProcessStage({
fragmentShader: `
uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
uniform mat4 grayscaleMatrix;
void main() {
vec4 color = texture2D(colorTexture, v_textureCoordinates);
gl_FragColor = vec4((grayscaleMatrix * vec4(color.rgb, 1.0)).rgb, color.a);
}
`,
uniforms: {
grayscaleMatrix: grayscaleMatrix
}
});
viewer.scene.postProcessStages.add(stage);
Этот метод влияет на всю сцену целиком, включая террейн, 3D Tiles и модели.
Иногда достаточно не полного обесцвечивания, а имитации чёрно-белого изображения через выравнивание каналов.
Используется простая нормализация:
const stage = new Cesium.PostProcessStage({
fragmentShader: `
uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
void main() {
vec4 color = texture2D(colorTexture, v_textureCoordinates);
float gray = (color.r + color.g + color.b) / 3.0;
gl_FragColor = vec4(vec3(gray), color.a);
}
`
});
viewer.scene.postProcessStages.add(stage);
Этот метод менее точен с точки зрения восприятия яркости, но дешевле в вычислениях.
CesiumJS включает набор готовых эффектов, которые можно комбинировать с пользовательскими настройками.
Хотя библиотека не предоставляет прямого “grayscale stage”, базовые эффекты можно использовать как основу:
Пример цепочки:
viewer.scene.postProcessStages.add(
Cesium.PostProcessStageLibrary.createBrightnessStage()
);
Далее поверх накладывается grayscale-стадия.
При работе с геометрией (например, polygon, polyline, ellipse) применяется система материалов.
Чёрно-белый эффект можно добиться через фиксированный цвет материала:
const entity = viewer.entities.add({
polygon: {
hierarchy: Cesium.Cartesian3.fromDegreesArray([
-100.0, 30.0,
-90.0, 30.0,
-90.0, 40.0,
-100.0, 40.0
]),
material: Cesium.Color.GRAY
}
});
Однако данный способ не влияет на подложку и используется локально.
В сложных сценах с 3D Tiles, terrain и imagery один метод редко даёт полный результат. Используется комбинация:
Пример комплексной конфигурации:
const viewer = new Cesium.Viewer("cesiumContainer");
// 1. Подложка
viewer.imageryLayers.get(0).saturation = 0.0;
// 2. Постобработка
viewer.scene.postProcessStages.add(
new Cesium.PostProcessStage({
fragmentShader: `
uniform sampler2D colorTexture;
varying vec2 v_textureCoordinates;
void main() {
vec4 color = texture2D(colorTexture, v_textureCoordinates);
float gray = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
gl_FragColor = vec4(vec3(gray), color.a);
}
`
})
);
Постпроцессинг в CesiumJS выполняется на GPU и добавляет дополнительный проход рендеринга.
Факторы влияния:
Обесцвечивание через imageryLayer почти не влияет на производительность, тогда как full-screen shader увеличивает нагрузку линейно от разрешения экрана.
Разные источники данных реагируют на фильтры по-разному:
В результате только postProcessStage обеспечивает единообразный визуальный результат.
При необходимости тонкой настройки применяется кастомный GLSL-код. Основная задача — контроль вклада каждого канала.
Типовая структура:
float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));
Эта формула отличается от более «физически точной» версии и часто применяется для стилизованных картографических визуализаций, где требуется более мягкий контраст.
Чёрно-белый режим может конфликтовать с динамическим освещением Cesium:
При активных тенях grayscale визуально усиливает контраст границ, что может быть полезно для аналитических сцен, но снижает читаемость текстур.
Для стабилизации изображения часто дополнительно фиксируют:
viewer.scene.globe.enableLighting = false;
Типичная схема применения выглядит как многослойная цепочка:
Такой подход обеспечивает полный контроль над визуальным стилем сцены независимо от источников данных и сложности геометрии.