Black and white фильтр

Преобразование цветового пространства карты через слои изображений

Одним из наиболее прямых способов получения монохромного изображения сцены является управление параметрами слоя изображений (ImageryLayer). Каждый слой в CesiumJS может иметь настройки цветокоррекции, влияющие на итоговый рендер тайлов подложки.

Ключевой механизм — модификация насыщенности через HSV/HSB-подобные параметры, а также использование цветового смешивания.

Основная идея заключается в обнулении насыщенности:

  • снижение saturation до нуля
  • сохранение luminance (яркости)
  • сохранение hue (оттенка), который при нулевой насыщенности становится несущественным

Пример настройки слоя:

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 сцена визуально превращается в градации серого, сохраняя структуру освещения и контуры объектов.


Управление цветом через ColorBlendMode

Cesium предоставляет механизм смешивания цвета слоя с глобальным освещением сцены через ColorBlendMode.

Доступные режимы:

  • HIGHLIGHT
  • REPLACE
  • MIX

Для получения монохромного эффекта часто используется комбинация MIX и уменьшенной насыщенности.

layer.colorBlendMode = Cesium.ColorBlendMode.MIX;
layer.colorBlendAmount = 0.7;

Этот подход полезен, когда требуется частичное обесцвечивание, сохраняя визуальную дифференциацию объектов.


Постобработка сцены через PostProcessStage

Более универсальный метод — использование постобработки. В CesiumJS сцена может быть изменена на уровне финального кадра через PostProcessStage.

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

Грейскейл-матрица

Классическая формула яркости:

  • 0.2126 R + 0.7152 G + 0.0722 B

Эта модель соответствует восприятию человеческого глаза.

Реализация через 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);

Этот метод менее точен с точки зрения восприятия яркости, но дешевле в вычислениях.


Использование встроенных эффектов PostProcessStageLibrary

CesiumJS включает набор готовых эффектов, которые можно комбинировать с пользовательскими настройками.

Хотя библиотека не предоставляет прямого “grayscale stage”, базовые эффекты можно использовать как основу:

  • улучшение контраста сцены перед обесцвечиванием
  • усиление глубины цвета перед последующим обнулением насыщенности

Пример цепочки:

viewer.scene.postProcessStages.add(
  Cesium.PostProcessStageLibrary.createBrightnessStage()
);

Далее поверх накладывается grayscale-стадия.


Обесцвечивание через Material системы

При работе с геометрией (например, 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 один метод редко даёт полный результат. Используется комбинация:

  • imageryLayer.saturation = 0
  • PostProcessStage grayscale
  • корректировка brightness/contrast

Пример комплексной конфигурации:

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 и добавляет дополнительный проход рендеринга.

Факторы влияния:

  • разрешение canvas (главный фактор)
  • количество активных PostProcessStage
  • сложность фрагментного шейдера
  • наличие 3D Tiles с высокой детализацией

Обесцвечивание через imageryLayer почти не влияет на производительность, тогда как full-screen shader увеличивает нагрузку линейно от разрешения экрана.


Поведение при разных типах данных сцены

Разные источники данных реагируют на фильтры по-разному:

  • ImageryLayer — полностью подчиняется saturation/contrast
  • TerrainProvider — влияет косвенно через освещение
  • 3D Tiles — обрабатываются в постпроцессе
  • Entities — зависят от material и глобального шейдера

В результате только postProcessStage обеспечивает единообразный визуальный результат.


Использование шейдерной модели для точного контроля

При необходимости тонкой настройки применяется кастомный GLSL-код. Основная задача — контроль вклада каждого канала.

Типовая структура:

float gray = dot(color.rgb, vec3(0.299, 0.587, 0.114));

Эта формула отличается от более «физически точной» версии и часто применяется для стилизованных картографических визуализаций, где требуется более мягкий контраст.


Комбинирование с освещением сцены

Чёрно-белый режим может конфликтовать с динамическим освещением Cesium:

  • Sun Lighting
  • Shadows
  • HDR rendering

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

Для стабилизации изображения часто дополнительно фиксируют:

viewer.scene.globe.enableLighting = false;

Итоговая архитектура визуального фильтра

Типичная схема применения выглядит как многослойная цепочка:

  1. ImageryLayer (снижение насыщенности)
  2. Terrain shading (фиксированное освещение)
  3. 3D Tiles rendering
  4. PostProcessStage (финальное преобразование цвета)
  5. UI overlay (без изменений)

Такой подход обеспечивает полный контроль над визуальным стилем сцены независимо от источников данных и сложности геометрии.