Материал Water в CesiumJS представляет собой процедурный шейдерный
материал, предназначенный для имитации динамической поверхности воды на
3D-геометрии. Он основан на системе материалов Cesium и работает как на
примитивах, так и на сущностях, поддерживающих
MaterialAppearance и MaterialProperty.
Основная задача материала — визуальная симуляция волн, отражений и
цветовых градиентов водной поверхности без необходимости использования
сложных физических моделей жидкости.
Система материалов CesiumJS строится вокруг концепции процедурных шейдеров, управляемых через JavaScript API. Каждый материал компилируется в GLSL и интегрируется в пайплайн рендеринга.
Материал Water является одним из предустановленных типов и регистрируется в системе как:
Cesium.Material.WaterType
Создание материала происходит через фабрику:
material: Cesium.Material.fromType("Water", {
baseWaterColor: new Cesium.Color(0.0, 0.3, 0.5, 1.0),
blendColor: new Cesium.Color(0.0, 0.0, 0.0, 0.0),
normalMapUrl: "path/to/normal-map.png",
frequency: 10.0,
animationSpeed: 0.01,
amplitude: 1.0,
specularIntensity: 0.5
})
Каждый параметр влияет на итоговое поведение шейдера и визуальное восприятие поверхности.
Определяет базовый цвет водной поверхности. Используется как фундамент для всех дальнейших вычислений освещения и смешивания.
Типично представляет собой оттенки синего и зелёного спектра:
baseWaterColor: new Cesium.Color(0.0, 0.2, 0.4, 1.0)
Этот цвет участвует в диффузной составляющей шейдера и задаёт общий тон воды.
Параметр, отвечающий за смешивание воды с окружающей сценой. Используется для имитации мутности, глубины и эффекта рассеивания света.
blendColor: new Cesium.Color(0.0, 0.0, 0.0, 0.2)
При увеличении альфа-компоненты усиливается эффект затемнения и «глубины».
Ключевой параметр, определяющий структуру поверхности воды. Нормал-карта используется для создания иллюзии волн без изменения геометрии.
normalMapUrl: "waterNormals.jpg"
Шейдер использует эту текстуру для модификации нормалей фрагментов, что создаёт эффект ряби и мелких волн.
Частота волн определяет плотность повторения нормалей на поверхности.
frequency: 10.0
Высокие значения создают мелкую, «шумную» поверхность, низкие — крупные и плавные волны.
Скорость анимации управляет темпом смещения текстурных координат во времени.
animationSpeed: 0.02
Внутри шейдера используется глобальное время сцены
(czm_frameNumber или czm_time) для смещения
UV-координат.
Амплитуда влияет на силу визуального искажения нормалей.
amplitude: 1.0
Чем выше значение, тем более выраженными становятся пики и впадины волн.
Отвечает за силу зеркальных бликов от источников света.
specularIntensity: 0.8
Используется в расчёте specular-компоненты модели освещения.
Материал может быть применён к геометрии через Primitive
и MaterialAppearance. Это наиболее гибкий способ интеграции
воды в сцену.
const waterPrimitive = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.RectangleGeometry({
rectangle: Cesium.Rectangle.fromDegrees(-80, 20, -70, 30),
vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT
})
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
material: Cesium.Material.fromType("Water", {
baseWaterColor: Cesium.Color.AQUA,
normalMapUrl: "waterNormals.jpg",
frequency: 12.0,
animationSpeed: 0.03,
amplitude: 0.7
})
})
});
В этом случае поверхность воды накладывается на прямоугольную геометрию, которая интерпретируется как участок эллипсоида Земли.
Entity API упрощает создание водных поверхностей за счёт абстракции геометрии и материалов.
viewer.entities.add({
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(-100.0, 25.0, -90.0, 35.0),
material: new Cesium.MaterialProperty({
fabric: {
type: "Water",
uniforms: {
baseWaterColor: Cesium.Color.BLUE,
blendColor: Cesium.Color.BLACK.withAlpha(0.3),
normalMapUrl: "waterNormals.jpg",
frequency: 8.0,
animationSpeed: 0.02,
amplitude: 1.2,
specularIntensity: 0.6
}
}
})
}
});
MaterialProperty обеспечивает реактивное обновление параметров, что позволяет динамически изменять поведение воды во времени.
Шейдер Water состоит из нескольких этапов обработки:
Упрощённая логика фрагментного шейдера:
vec2 uv = st * frequency;
uv += time * animationSpeed;
vec3 normal = texture(normalMap, uv).rgb;
normal = normalize(normal * 2.0 - 1.0);
float diffuse = max(dot(normal, lightDirection), 0.0);
float specular = pow(diffuse, 32.0) * specularIntensity;
vec3 color = baseWaterColor.rgb * diffuse;
color += specular;
В реальной реализации Cesium учитывает также атмосферное рассеивание, глубину и параметры камеры.
Анимация водной поверхности в CesiumJS привязана к глобальному
времени сцены. Используется Scene clock:
viewer.clock.shouldAnimate = true;
Внутри шейдера время поступает как uniform, который обновляется каждый кадр. Это обеспечивает непрерывное движение волн без необходимости ручного обновления состояния материала.
Смещение текстур реализуется как функция времени:
UV(t) = UV + t * animationSpeed
При этом разные слои нормалей могут иметь различную скорость, создавая эффект сложной поверхности.
Более сложные водные поверхности создаются путём наложения нескольких нормал-карт с разными параметрами:
Это достигается либо модификацией шейдера, либо использованием нескольких текстур в одном материале.
Концептуальная схема:
frequency: 6.0 + 14.0
amplitude: 0.5 + 1.5
animationSpeed: 0.01 + 0.03
Каждый слой вносит собственный вклад в итоговую нормаль поверхности.
Water-материал не реализует полноценные физические отражения экранного пространства (SSR), однако использует приближённые модели бликов и отражений неба.
Основные компоненты:
При низком угле обзора поверхность становится более отражающей, что имитирует эффект Френеля.
При использовании Water-материала критически важно учитывать нагрузку на GPU:
MaterialAppearance предпочтительнее
кастомных шейдеров при стандартных сценарияхТакже важным фактором является количество одновременно анимируемых водных поверхностей в сцене.
Несмотря на визуальную выразительность, материал имеет ряд ограничений:
Эти ограничения компенсируются производительностью и простотой интеграции в глобусную модель CesiumJS.
Water-материал тесно связан с системой рендеринга сцены Cesium:
Это позволяет размещать водные поверхности на любых участках планеты без дополнительных преобразований координат.
Water-материал применяется для:
При масштабировании на глобальный уровень важным становится баланс между качеством нормал-карт и частотой обновления анимации, чтобы избежать артефактов на больших расстояниях.