В основе WebGL-подсистемы лежит принцип аппаратного ускорения через GPU, при котором большая часть вычислений перенесена из JavaScript в графический конвейер. В отличие от Canvas2D-рендера, где каждый объект отрисовывается последовательно на CPU, WebGL-слой оперирует буферами данных, шейдерами и состоянием контекста рендеринга.
Внутренняя архитектура OpenLayers WebGL можно условно разделить на три уровня:
Ключевым отличием является то, что слой не управляет отдельными объектами. Вместо этого он оперирует массивами признаков, преобразованными в GPU-буферы.
WebGL-рендер в OpenLayers основан на стандартном графическом конвейере:
На уровне OpenLayers этот процесс абстрагирован, но при работе с WebGL напрямую важно понимать соответствие между JavaScript-данными и GPU-структурами.
WebGL-контекст создаётся один раз на канвасе карты и переиспользуется всеми WebGL-слоями. Контекст содержит:
Смена состояния WebGL — дорогая операция, поэтому OpenLayers минимизирует переключения программ шейдеров и буферов.
Для растровых данных используется слой WebGLTile, который агрегирует тайлы и отправляет их в GPU как текстуры.
Основные особенности:
Пример базовой конфигурации:
import WebGLTileLayer from 'ol/layer/WebGLTile';
import XYZ from 'ol/source/XYZ';
const layer = new WebGLTileLayer({
source: new XYZ({
url: 'https://tile-server/{z}/{x}/{y}.png'
}),
style: {
color: [
'interpolate',
['linear'],
['band', 1],
0, 'blue',
255, 'red'
]
}
});
В данном случае выражение style компилируется в GLSL-эквивалент, который выполняется на GPU для каждого пикселя.
Для точечных данных используется WebGLPoints, оптимизированный для миллионов объектов.
Особенность модели заключается в том, что каждая точка представляется как запись в буфере:
Пример:
import WebGLPointsLayer from 'ol/layer/WebGLPoints';
import VectorSource from 'ol/source/Vector';
const layer = new WebGLPointsLayer({
source: new VectorSource({
features: featuresArray
}),
style: {
symbol: {
symbolType: 'circle',
size: 8,
color: [
'case',
['>', ['get', 'value'], 50],
'red',
'green'
]
}
}
});
Вся логика условий трансформируется в GPU-выражения без участия CPU на этапе рендеринга.
WebGL-слой в OpenLayers использует автоматически генерируемые GLSL-шейдеры. Они состоят из двух основных частей:
Отвечает за преобразование координат:
Упрощённый пример:
attribute vec2 a_position;
uniform mat4 u_projectionMatrix;
void main() {
gl_Position = u_projectionMatrix * vec4(a_position, 0.0, 1.0);
}
Отвечает за цвет пикселя:
precision mediump float;
uniform vec4 u_color;
void main() {
gl_FragColor = u_color;
}
OpenLayers расширяет эту модель через декларативные style-выражения.
Одной из ключевых особенностей WebGL-слоя является представление стиля как вычисляемого выражения, а не как статического объекта.
Пример выражений:
['get', 'property']['+', a, b]['interpolate', ...]['case', condition, value1, value2]Эти выражения транслируются в GLSL-код, который выполняется на GPU.
Пример цветовой логики:
style: {
color: [
'interpolate',
['linear'],
['get', 'temperature'],
-20, 'blue',
0, 'white',
30, 'red'
]
}
На уровне GPU это превращается в серию условных ветвлений и интерполяций.
WebGL-рендер требует строгой работы с памятью GPU:
Каждый слой стремится:
При изменении данных происходит частичная пересборка буферов:
Важно, что GPU не получает JavaScript-объекты, только бинарные массивы.
В WebGL-слое координаты заранее проецируются в пространство карты.
Типичный pipeline:
Это позволяет выполнять финальную трансформацию исключительно в vertex shader.
Несмотря на высокую производительность, модель имеет ограничения:
Особенно критичным является лимит на сложность выражений стиля, так как они компилируются в шейдер.
При работе с WebGL-слоем часто требуется анализ сгенерированного GLSL:
Типичная проблема — переполнение precision, приводящее к артефактам цвета или геометрии.
OpenLayers позволяет расширять WebGL-пайплайн через кастомные стили и фильтры.
Пример концептуального фильтра:
Фрагментная логика может включать:
WebGL-рендер не заменяет событийную модель. Hit detection реализуется через:
Это позволяет определять объект под курсором без CPU-итерации по features.
При работе с миллионами объектов ключевыми становятся:
Наиболее эффективная модель — сочетание WebGLPoints и тайловой сегментации данных.
В одной карте могут сосуществовать разные рендереры:
Порядок компоновки контролируется z-index и internal render order.
Каждый кадр WebGL-рендера включает:
Ключевая оптимизация — пропуск шагов при отсутствии изменений состояния.