LightingEffect — механизм системы освещения в Deck.gl,
предназначенный для моделирования взаимодействия источников света с
трёхмерными объектами сцены. Эффект используется совместно с слоями,
поддерживающими материалы и расчёт освещения, такими как
PolygonLayer, SolidPolygonLayer,
ColumnLayer, HexagonLayer,
ScenegraphLayer, SimpleMeshLayer и рядом
других.
Основная задача LightingEffect заключается в повышении
визуальной реалистичности сцены. Без освещения большинство 3D-объектов
отображаются плоскими и лишёнными глубины. При добавлении источников
света появляются:
Архитектурно LightingEffect представляет собой объект
эффекта, который передаётся в параметр effects экземпляра
Deck.
Система освещения Deck.gl состоит из нескольких компонентов:
Схема взаимодействия выглядит следующим образом:
Light Sources
↓
LightingEffect
↓
Layer Materials
↓
Shaders
↓
Rendered Scene
Каждый источник света описывает собственные характеристики:
LightingEffect объединяет все источники света в единую
систему и передаёт их в графический конвейер рендеринга.
Базовый пример создания эффекта освещения:
import {Deck} from '@deck.gl/core';
import {LightingEffect, AmbientLight} from '@deck.gl/core';
const ambientLight = new AmbientLight({
color: [255, 255, 255],
intensity: 1.0
});
const lightingEffect = new LightingEffect({
ambientLight
});
const deck = new Deck({
initialViewState,
controller: true,
effects: [lightingEffect],
layers: []
});
В данном примере создаётся один источник окружающего света и подключается к сцене.
AmbientLight моделирует рассеянное освещение окружающей
среды.
Такой свет не имеет конкретного направления и воздействует на все объекты одинаково.
В реальном мире аналогом служит отражённый свет атмосферы, облаков, стен зданий и прочих поверхностей.
import {AmbientLight} from '@deck.gl/core';
const ambientLight = new AmbientLight({
color: [255, 255, 255],
intensity: 2.0
});
Определяет цвет освещения.
color: [255, 255, 255]
Белый свет.
Пример тёплого освещения:
color: [255, 230, 180]
Пример холодного освещения:
color: [180, 220, 255]
Указывает силу света.
intensity: 1.0
Возможные значения:
0.2
0.5
1.0
2.0
5.0
Большие значения приводят к пересвету сцены.
DirectionalLight представляет бесконечно удалённый
источник света.
Типичный пример — солнечный свет.
Все лучи такого источника считаются параллельными.
import {DirectionalLight} from '@deck.gl/core';
const sunlight = new DirectionalLight({
color: [255, 255, 255],
intensity: 1.0,
direction: [-1, -3, -1]
});
Определяет направление распространения света.
Примеры:
direction: [1, 0, 0]
Свет справа.
direction: [-1, 0, 0]
Свет слева.
direction: [0, -1, 0]
Свет сверху.
direction: [0, 1, 0]
Свет снизу.
direction: [-1, -3, -2]
Солнечный свет под углом.
Закатное освещение:
const sunlight = new DirectionalLight({
color: [255, 180, 100],
intensity: 1.5,
direction: [-1, -2, -1]
});
Пасмурная погода:
const sunlight = new DirectionalLight({
color: [210, 220, 255],
intensity: 0.7,
direction: [-1, -3, -2]
});
PointLight моделирует точечный источник света.
Аналогами являются:
Свет распространяется во все стороны от заданной точки.
import {PointLight} from '@deck.gl/core';
const pointLight = new PointLight({
color: [255, 255, 255],
intensity: 2.0,
position: [-122.4, 37.8, 1000]
});
Координаты источника света:
position: [longitude, latitude, altitude]
Пример:
position: [
-122.45,
37.80,
500
]
const redLight = new PointLight({
color: [255, 0, 0],
intensity: 2,
position: [-122.4, 37.8, 1000]
});
const blueLight = new PointLight({
color: [0, 0, 255],
intensity: 2,
position: [-122.42, 37.82, 1000]
});
Подобный подход используется для создания художественной подсветки объектов.
На практике почти всегда применяется несколько источников одновременно.
Пример:
const ambientLight = new AmbientLight({
color: [255, 255, 255],
intensity: 1
});
const sunLight = new DirectionalLight({
color: [255, 255, 255],
intensity: 1,
direction: [-1, -3, -2]
});
const pointLight = new PointLight({
color: [255, 240, 200],
intensity: 2,
position: [-122.4, 37.8, 1000]
});
const lightingEffect = new LightingEffect({
ambientLight,
sunLight,
pointLight
});
Такая конфигурация обеспечивает:
Освещение работает совместно с материалами.
Материал определяет реакцию поверхности на свет.
Пример:
material: {
ambient: 0.4,
diffuse: 0.6,
shininess: 32,
specularColor: [255, 255, 255]
}
Уровень реакции на окружающий свет.
ambient: 0.4
Большое значение делает объект более ярким даже без прямого освещения.
Коэффициент рассеянного отражения.
diffuse: 0.6
Определяет основной вклад направленного света.
Степень блеска поверхности.
shininess: 32
Примеры:
shininess: 8
Матовая поверхность.
shininess: 64
Глянцевая поверхность.
shininess: 128
Полированная поверхность.
Цвет зеркальных бликов.
specularColor: [255, 255, 255]
Золотистые блики:
specularColor: [255, 220, 120]
Пример для ColumnLayer:
new ColumnLayer({
id: 'columns',
data,
diskResolution: 12,
radius: 50,
extruded: true,
getPosition: d => d.position,
getElevation: d => d.height,
material: {
ambient: 0.3,
diffuse: 0.7,
shininess: 64,
specularColor: [255, 255, 255]
}
});
Экструзия должна быть включена:
new PolygonLayer({
id: 'buildings',
data,
extruded: true,
wireframe: false,
filled: true,
getElevation: d => d.height
});
Без экструзии освещение практически не влияет на внешний вид слоя, поскольку отсутствуют объёмные поверхности.
ColumnLayer является одним из наиболее наглядных
примеров применения освещения.
new ColumnLayer({
id: 'population',
data,
extruded: true,
radius: 100,
getPosition: d => d.coordinates,
getElevation: d => d.population
});
Боковые грани начинают реагировать на направление света, что делает столбцы визуально объёмными.
Для трёхмерных гексагонов:
new HexagonLayer({
id: 'hex',
data,
extruded: true,
radius: 500,
elevationScale: 20
});
Различия в освещении помогают лучше воспринимать перепады высоты между соседними ячейками.
ScenegraphLayer активно использует систему освещения при
отображении моделей GLTF.
new ScenegraphLayer({
id: 'cars',
data,
scenegraph: '/models/car.glb',
getPosition: d => d.position
});
В данном случае освещение влияет на:
Некоторые источники света поддерживают генерацию теней.
const sunlight = new DirectionalLight({
color: [255, 255, 255],
intensity: 1.0,
direction: [-1, -3, -1],
shadow: true
});
Тени существенно увеличивают реалистичность сцены.
Deck.gl использует технологию Shadow Maps.
Процесс состоит из двух этапов:
Схема:
Light
↓
Depth Map
↓
Shadow Calculation
↓
Final Rendering
const ambientLight = new AmbientLight({
intensity: 1
});
const sunLight = new DirectionalLight({
direction: [-1, -3, -2],
intensity: 1.5,
shadow: true
});
const lightingEffect = new LightingEffect({
ambientLight,
sunLight
});
Подключение:
const deck = new Deck({
effects: [lightingEffect],
layers
});
Освещение оказывает влияние на быстродействие.
Наиболее затратными являются:
По степени нагрузки:
AmbientLight Низкая
DirectionalLight Низкая
PointLight Средняя
Shadows Высокая
Наиболее распространённая конфигурация:
AmbientLight
DirectionalLight
Она обеспечивает хорошее качество изображения при минимальных затратах ресурсов.
Рекомендуемая комбинация:
AmbientLight
DirectionalLight
Shadow Mapping
Позволяет отчётливо отображать выступающие элементы зданий и особенности фасадов.
Часто используется набор:
AmbientLight
DirectionalLight
PointLight
Локальные источники света помогают выделять важные зоны производства или оборудования.
Для автомобилей, самолётов и кораблей особенно важны параметры материала:
material: {
ambient: 0.25,
diffuse: 0.6,
shininess: 128,
specularColor: [255, 255, 255]
}
Высокое значение shininess позволяет получить
реалистичные отражающие поверхности.
import {
Deck,
LightingEffect,
AmbientLight,
DirectionalLight,
PointLight
} from '@deck.gl/core';
const ambientLight = new AmbientLight({
color: [255, 255, 255],
intensity: 1.0
});
const sunLight = new DirectionalLight({
color: [255, 255, 255],
intensity: 1.5,
direction: [-1, -3, -2],
shadow: true
});
const pointLight = new PointLight({
color: [255, 240, 200],
intensity: 2,
position: [-122.4, 37.8, 1000]
});
const lightingEffect = new LightingEffect({
ambientLight,
sunLight,
pointLight
});
const deck = new Deck({
initialViewState,
controller: true,
effects: [lightingEffect],
layers: [
new ColumnLayer({
id: 'columns',
data,
extruded: true,
getPosition: d => d.position,
getElevation: d => d.height,
material: {
ambient: 0.3,
diffuse: 0.6,
shininess: 64,
specularColor: [255, 255, 255]
}
})
]
});
Данная конфигурация объединяет все основные возможности
LightingEffect: окружающее освещение, направленный
солнечный свет, локальную подсветку, материалы поверхностей и генерацию
теней для формирования реалистичной трёхмерной сцены в Deck.gl.