Effect-классы в deck.gl представляют собой механизм расширения визуального рендеринга на уровне сцены, позволяя применять глобальные или слой-специфичные визуальные преобразования без модификации исходных геометрических данных. Архитектурно система эффектов отделена от слоёв (layers) и работает на этапе финального рендеринга через композицию шейдеров и постобработки.
Рендеринг в deck.gl строится вокруг последовательности этапов: подготовка данных слоя, рендеринг в framebuffer и последующая композиция результата. Effect-классы подключаются после того, как слои сформировали изображение в буфере кадра.
Основная идея заключается в том, что эффект:
Механизм эффектов интегрирован через EffectManager,
который управляет жизненным циклом эффектов и их применением при каждом
кадре.
Корневой абстрактный класс Effect определяет интерфейс,
который обязаны реализовать все визуальные эффекты.
Ключевые методы и свойства:
id — уникальный идентификатор эффектаenabled — флаг активностиapply(...args) — основная функция применения
эффектаcleanup() — освобождение ресурсов WebGLparams — конфигурационные параметры эффектаБазовая логика выглядит концептуально так:
class CustomEffect {
constructor() {
this.id = 'custom-effect';
this.enabled = true;
}
apply({gl, framebuffer, inputBuffer, outputBuffer}) {
// логика обработки кадра
}
cleanup() {
// удаление шейдеров, буферов
}
}
В реальной архитектуре deck.gl эффекты тесно связаны с WebGL контекстом и могут использовать как чистую постобработку, так и шейдерные модификации рендеринга слоёв.
EffectManager является центральным координатором.
Он:
При каждом кадре выполняется следующий порядок:
Особенность системы заключается в том, что эффекты могут быть цепочечными, то есть результат одного эффекта становится входом для следующего.
Постобработка выполняется после рендеринга всей сцены и работает с изображением как с текстурой.
Характерные задачи:
Принцип работы основан на fullscreen quad shader:
apply({gl, inputBuffer, outputBuffer}) {
this.program.setUniforms({
texture: inputBuffer
});
drawFullScreenQuad(gl, this.program, outputBuffer);
}
Ключевая особенность — отсутствие привязки к геометрии сцены.
Один из наиболее используемых эффектов — система освещения. Он интегрируется не как постобработка, а как параметризация шейдеров слоёв.
LightingEffect передаёт в GPU:
Типы источников света:
Пример конфигурации:
import {LightingEffect} from '@deck.gl/core';
const lightingEffect = new LightingEffect({
ambientLight: {
color: [255, 255, 255],
intensity: 0.5
},
directionalLight: {
color: [255, 255, 255],
direction: [-1, -2, -3],
intensity: 1.0
}
});
LightingEffect передаёт uniform-переменные в шейдеры слоёв, где выполняется расчёт освещения на пиксельном уровне.
PostProcessEffect представляет собой класс-обёртку над фрагментными шейдерами, применяемыми ко всему кадру.
Он используется как базовый строительный блок для эффектов:
Пример логики шейдера:
const fs = `
precision highp float;
varying vec2 vTexCoord;
uniform sampler2D texture;
void main() {
vec4 color = texture2D(texture, vTexCoord);
gl_FragColor = vec4(color.rgb * 1.2, color.a);
}
`;
PostProcessEffect позволяет подключать произвольную GLSL-логику без изменения слоя.
Слои deck.gl могут поддерживать эффекты на двух уровнях:
LightingEffect, например, влияет на все слои, поддерживающие освещение.
Внутренне слой получает массив эффектов:
layer.draw({effects});
И затем каждый эффект может:
Последовательность критична:
Некоторые эффекты требуют знания предыдущего состояния сцены, например bloom или motion blur, поэтому используются ping-pong buffers.
Effect-система напрямую работает с WebGL и оказывает влияние на:
Основные оптимизации:
Особенно дорогими являются эффекты с несколькими проходами (multi-pass shaders).
Создание собственного эффекта требует реализации логики на уровне WebGL.
Структура кастомного эффекта:
class InvertEffect {
constructor() {
this.id = 'invert-effect';
}
setup(gl) {
this.program = new ShaderProgram(gl, {
vs,
fs
});
}
apply({inputBuffer, outputBuffer, gl}) {
this.program.setUniforms({
texture: inputBuffer
});
drawFullScreenQuad(gl, this.program, outputBuffer);
}
}
Ключевые аспекты:
deck.gl использует модульную систему шейдеров. Effect может внедряться через:
Пример расширения:
const shaderModule = {
name: 'custom-light',
fs: `
vec3 applyCustomLight(vec3 color) {
return color * 1.1;
}
`
};
Несмотря на гибкость, система имеет ряд ограничений:
В сценах с большим количеством слоёв эффекты становятся инструментом унификации визуального стиля:
Комбинация нескольких эффектов формирует эффектный pipeline:
Такая композиция позволяет отделить визуальную логику от геометрической структуры данных, сохраняя масштабируемость рендеринга.