Тени позволяют повысить визуальную реалистичность трёхмерных сцен, улучшить восприятие глубины объектов и облегчить анализ пространственных данных. При отображении зданий, колонок, трёхмерных сеток, моделей и других объёмных объектов наличие корректных теней помогает быстрее оценивать взаимное расположение элементов и их высоту.
В Deck.gl поддержка теней реализована через систему освещения. Для формирования теней используются специальные источники света, способные генерировать карту глубины (shadow map), которая затем применяется во время рендеринга сцены.
Тени доступны только для слоёв, поддерживающих освещение и материалы.
Механизм теней в Deck.gl основан на классическом подходе Shadow Mapping:
Схема работы выглядит следующим образом:
Источник света
|
v
Карта глубины
|
v
Проверка видимости
|
v
Отрисовка теней
Этот подход обеспечивает высокую производительность даже при большом количестве объектов.
Для корректного отображения теней необходимо выполнение нескольких условий:
Тени работают только совместно с системой LightingEffect.
import {LightingEffect} from '@deck.gl/core';
Источник света должен поддерживать создание теней.
Наиболее распространённый вариант:
import {SunLight} from '@deck.gl/core';
или
import {DirectionalLight} from '@deck.gl/core';
Слой должен использовать параметры материала.
Например:
material: true
или объект Material.
Окружающее освещение равномерно освещает всю сцену.
import {AmbientLight} from '@deck.gl/core';
const ambientLight = new AmbientLight({
color: [255, 255, 255],
intensity: 1.0
});
Особенности:
Направленный свет имитирует удалённый источник света.
import {DirectionalLight} from '@deck.gl/core';
const directionalLight = new DirectionalLight({
color: [255, 255, 255],
intensity: 1.0,
direction: [-1, -3, -1]
});
Преимущества:
Для создания теней необходимо активировать соответствующую возможность.
const directionalLight = new DirectionalLight({
color: [255, 255, 255],
intensity: 1,
direction: [-1, -3, -1],
shadow: true
});
SunLight является специализированным вариантом направленного света.
Он рассчитывает положение солнца по времени суток и координатам.
import {SunLight} from '@deck.gl/core';
const sunlight = new SunLight({
timestamp: Date.UTC(
2025,
5,
15,
12
)
});
Особенности:
После настройки источников света необходимо создать объект эффекта освещения.
const lightingEffect = new LightingEffect({
ambientLight,
directionalLight
});
Подключение эффекта:
new Deck({
effects: [lightingEffect]
});
Если используется несколько источников света:
const lightingEffect = new LightingEffect({
ambientLight,
sunlight,
secondaryLight
});
Для генерации теней необходимо указать список источников света, которые должны участвовать в построении shadow map.
Пример настройки:
const lightingEffect = new LightingEffect({
ambientLight,
sunlight
});
lightingEffect.shadowColor = [0, 0, 0, 180];
Параметр shadowColor задаёт цвет и прозрачность
теней.
Более тёмные тени:
lightingEffect.shadowColor = [
0,
0,
0,
220
];
Мягкие тени:
lightingEffect.shadowColor = [
0,
0,
0,
100
];
Качество отображения теней во многом зависит от параметров материала.
Пример материала:
const material = {
ambient: 0.3,
diffuse: 0.7,
shininess: 32,
specularColor: [255, 255, 255]
};
Использование:
new ColumnLayer({
id: 'columns',
data,
material
});
Назначение параметров:
| Параметр | Описание |
|---|---|
| ambient | Влияние окружающего света |
| diffuse | Рассеянное освещение |
| shininess | Размер блика |
| specularColor | Цвет отражения |
ColumnLayer является одним из наиболее распространённых слоёв с поддержкой теней.
new ColumnLayer({
id: 'buildings',
data,
extruded: true,
radius: 100,
elevationScale: 10,
material
});
Тени особенно полезны при визуализации:
При использовании экструдированных полигонов тени позволяют создавать полноценные трёхмерные карты.
new GeoJsonLayer({
id: 'geojson',
data,
extruded: true,
filled: true,
material,
getElevation: f => f.properties.height
});
Применение:
Для пользовательских полигонов поддержка теней включается автоматически при использовании экструзии.
new PolygonLayer({
id: 'polygons',
data,
extruded: true,
material,
getElevation: d => d.height
});
Чем выше объект, тем более заметной становится его тень.
Трёхмерные модели особенно выигрывают от использования теней.
new ScenegraphLayer({
id: 'cars',
data,
scenegraph: '/models/car.glb',
getPosition: d => d.position,
sizeScale: 5
});
Преимущества:
Изменяя интенсивность света, можно управлять выраженностью теней.
Слабый свет:
const sunlight = new SunLight({
timestamp: Date.now(),
intensity: 0.5
});
Сильный свет:
const sunlight = new SunLight({
timestamp: Date.now(),
intensity: 3
});
Повышение интенсивности обычно делает границы теней более заметными.
Для DirectionalLight направление определяется вектором.
direction: [-1, -1, -1]
Тень будет направлена противоположно источнику света.
Примеры:
direction: [1, -1, 0]
Свет справа.
direction: [-1, -1, 0]
Свет слева.
direction: [0, -1, -1]
Свет спереди.
Для геопространственных приложений рекомендуется использовать SunLight.
Пример:
const sunlight = new SunLight({
timestamp: Date.UTC(
2025,
11,
21,
8,
0,
0
)
});
Утреннее солнце создаёт длинные тени.
Полуденное солнце:
const sunlight = new SunLight({
timestamp: Date.UTC(
2025,
11,
21,
12,
0,
0
)
});
Тени становятся значительно короче.
Генерация теней является одной из наиболее затратных операций в графическом конвейере.
На производительность влияют:
Особенно затратны сцены с тысячами экструдированных объектов.
В большинстве проектов достаточно одного источника света, генерирующего тени.
const lightingEffect = new LightingEffect({
ambientLight,
sunlight
});
Следует избегать чрезмерно детализированных моделей.
Например:
getElevation: d => d.height
часто оказывается эффективнее сложных трёхмерных моделей для отображения высоты объектов.
Level of Detail позволяет снижать детализацию удалённых объектов.
Преимущества:
При работе с картографическими приложениями полезно отображать только объекты в пределах текущего окна просмотра.
Это уменьшает количество объектов, участвующих в расчёте теней.
Распространённые причины отсутствия теней:
effects: [lightingEffect]
new LightingEffect({
ambientLight
});
В таком случае тени не будут создаваться.
Некоторые слои отображаются без освещения и не участвуют в системе теней.
Необходимо использовать слои с поддержкой освещения, например:
Если экструзия отключена:
extruded: false
тени становятся незаметными либо полностью отсутствуют.
import {
Deck,
AmbientLight,
SunLight,
LightingEffect
} from '@deck.gl/core';
import {GeoJsonLayer} from '@deck.gl/layers';
const ambientLight = new AmbientLight({
color: [255, 255, 255],
intensity: 1
});
const sunlight = new SunLight({
timestamp: Date.now(),
intensity: 2
});
const lightingEffect = new LightingEffect({
ambientLight,
sunlight
});
lightingEffect.shadowColor = [
0,
0,
0,
160
];
const material = {
ambient: 0.3,
diffuse: 0.7,
shininess: 32,
specularColor: [255, 255, 255]
};
const layer = new GeoJsonLayer({
id: 'buildings',
data: buildings,
extruded: true,
filled: true,
material,
getElevation: f => f.properties.height
});
new Deck({
initialViewState,
controller: true,
effects: [lightingEffect],
layers: [layer]
});
Такая конфигурация обеспечивает реалистичное солнечное освещение, корректное формирование теней, поддержку экструдированных объектов и хорошее соотношение между качеством визуализации и производительностью.