Отражения в трёхмерной визуализации позволяют создавать более реалистичное восприятие сцены за счёт имитации отражающей поверхности. В экосистеме Deck.gl отражения не являются встроенной функцией высокого уровня, как в полноценных игровых движках, однако могут быть реализованы через возможности WebGL, пользовательские шейдеры, настройку освещения и интеграцию с внешними рендерерами.
Отражения чаще всего используются для следующих объектов:
При работе с отражениями необходимо учитывать баланс между качеством изображения и производительностью, поскольку вычисление отражённых сцен требует дополнительных проходов рендеринга.
Отражение напрямую зависит от освещения сцены. Чем сложнее система света, тем более реалистичным становится отражённый объект.
В Deck.gl освещение обычно задаётся через объект
LightingEffect.
import {AmbientLight, DirectionalLight, LightingEffect} from '@deck.gl/core';
const ambientLight = new AmbientLight({
color: [255, 255, 255],
intensity: 1.0
});
const sunLight = new DirectionalLight({
color: [255, 255, 255],
intensity: 2.0,
direction: [-1, -3, -1]
});
const lightingEffect = new LightingEffect({
ambientLight,
sunLight
});
Даже если полноценное отражение отсутствует, качественное освещение создаёт визуальную иллюзию отражающих поверхностей благодаря бликам и изменению яркости в зависимости от угла обзора.
Наиболее простой способ создания эффекта отражения заключается в использовании свойств материала.
Для слоёв, поддерживающих освещение, можно задавать параметры материала:
material: {
ambient: 0.2,
diffuse: 0.6,
shininess: 128,
specularColor: [255, 255, 255]
}
Описание параметров:
| Параметр | Назначение |
|---|---|
| ambient | Вклад окружающего освещения |
| diffuse | Интенсивность рассеянного света |
| shininess | Размер и резкость блика |
| specularColor | Цвет зеркального отражения |
Большие значения shininess позволяют создавать
впечатление полированной поверхности.
Пример для слоя зданий:
new ScenegraphLayer({
id: 'buildings',
data,
scenegraph: '/models/building.glb',
material: {
ambient: 0.1,
diffuse: 0.5,
shininess: 256,
specularColor: [255, 255, 255]
}
});
Такой подход не создаёт настоящих отражений окружающей среды, но обеспечивает характерный зеркальный блеск.
Наиболее распространённой техникой является Environment Mapping.
Суть метода заключается в использовании кубической текстуры, содержащей изображения окружающего пространства.
Схема работы:
Визуально объект начинает отражать не реальную сцену, а заранее подготовленное окружение.
Cube Map состоит из шести изображений:
Структура файлов может выглядеть следующим образом:
skybox/
├── px.jpg
├── nx.jpg
├── py.jpg
├── ny.jpg
├── pz.jpg
└── nz.jpg
Каждая сторона представляет одну грань виртуального куба.
Deck.gl позволяет расширять базовые слои через механизм шейдеров.
Создание собственного слоя:
import {Layer} from '@deck.gl/core';
class ReflectiveLayer extends Layer {
getShaders() {
return {
vs: vertexShader,
fs: fragmentShader,
modules: []
};
}
}
Внутри фрагментного шейдера выполняется выборка данных из кубической карты.
uniform samplerCube uCubeMap;
vec3 reflectedDir =
reflect(viewDirection, normal);
vec4 reflectionColor =
textureCube(
uCubeMap,
reflectedDir
);
Функция reflect() является встроенной функцией GLSL и
вычисляет направление отражённого луча.
Отражение вычисляется на основе нормали поверхности и направления взгляда.
Используется выражение:
R=I-2(NI)N
где:
R — отражённый вектор;I — входящий луч;N — нормаль поверхности.Эта формула лежит в основе большинства реализаций отражений в графических движках и WebGL-приложениях.
Статические карты окружения подходят не всегда.
Если сцена постоянно изменяется, требуется динамическое окружение.
Алгоритм выглядит следующим образом:
Схема обеспечивает актуальное отражение окружающих объектов.
Недостатки:
Поэтому метод применяется только для небольшого количества объектов.
Одним из самых востребованных сценариев является отражение воды.
Обычно применяется техника Render-to-Texture.
Основные этапы:
Схема позволяет получить отражение объектов над поверхностью воды.
Deck.gl использует инфраструктуру библиотеки luma.gl.
Пример создания framebuffer:
const framebuffer = device.createFramebuffer({
colorAttachments: [texture]
});
Во время дополнительного прохода рендеринга сцена записывается не на экран, а в созданную текстуру.
Для формирования отражения положение камеры отражается относительно плоскости воды.
Исходная камера:
{
x: 100,
y: 50,
z: 200
}
После отражения:
{
x: 100,
y: -50,
z: 200
}
Полученное изображение выглядит так, словно сцена наблюдается из-под поверхности.
Во фрагментном шейдере текстура применяется как источник отражённого изображения.
uniform sampler2D reflectionTexture;
vec4 reflection =
texture(
reflectionTexture,
uv
);
Затем отражение смешивается с базовым цветом поверхности.
vec4 finalColor =
mix(
waterColor,
reflection,
0.7
);
Коэффициент смешивания определяет силу отражения.
В реальном мире интенсивность отражения зависит от угла обзора.
Этот эффект называется эффектом Френеля.
При взгляде сверху отражение слабее.
При взгляде под острым углом отражение значительно сильнее.
Типичная реализация:
float fresnel =
pow(
1.0 - dot(viewDir, normal),
5.0
);
Далее коэффициент используется при смешивании цветов:
vec4 finalColor =
mix(
baseColor,
reflectionColor,
fresnel
);
Благодаря этому поверхность выглядит значительно реалистичнее.
ScenegraphLayer особенно часто используется для
отображения моделей формата GLTF и GLB.
Сами модели могут содержать материалы PBR.
Современные модели экспортируются из:
Материалы PBR включают:
Если модель содержит корректно настроенные параметры металличности и шероховатости, отражения автоматически выглядят гораздо правдоподобнее.
Для отражающих объектов важны два параметра.
Определяет степень металлического поведения материала.
0.0 = диэлектрик
1.0 = металл
Определяет шероховатость поверхности.
0.0 = зеркало
1.0 = матовая поверхность
Примеры:
| Материал | Metallic | Roughness |
|---|---|---|
| Зеркало | 1.0 | 0.0 |
| Хром | 1.0 | 0.05 |
| Стекло | 0.0 | 0.02 |
| Алюминий | 1.0 | 0.15 |
| Бетон | 0.0 | 0.95 |
Screen Space Reflections (SSR) — техника отражений, использующая уже отрисованное изображение экрана.
Преимущества:
Недостатки:
В стандартный набор Deck.gl SSR не входит, однако может быть реализован через пользовательские post-processing эффекты.
Deck.gl поддерживает систему эффектов постобработки.
Общий подход:
const deck = new Deck({
effects: [
lightingEffect,
customReflectionEffect
]
});
Собственный эффект может:
Такой подход часто применяется в крупных геопространственных визуализациях.
Отражения являются одной из самых ресурсоёмких частей рендеринга.
Основные методы оптимизации:
Вместо:
2048 × 2048
используется:
1024 × 1024
или
512 × 512
Вместо отражений на каждом объекте сцены отражения применяются только к:
Перестраивать карту окружения можно не каждый кадр.
Например:
setInterval(updateCubeMap, 100);
Это уменьшает нагрузку на видеокарту.
Сильное размытие позволяет использовать текстуры меньшего разрешения без заметной потери качества.
reflection =
blur(
reflectionTexture
);
Максимально реалистичный результат достигается при совместном использовании:
Такая комбинация позволяет строить визуально сложные сцены в Deck.gl, включающие городские модели, инфраструктурные объекты, цифровые двойники территорий и высокодетализированные трёхмерные геопространственные приложения.