Instanced rendering в контексте Deck.gl представляет собой ключевую технику GPU-оптимизации, позволяющую отрисовывать тысячи и миллионы однотипных геометрических примитивов с минимальными затратами на CPU и передачу данных в WebGL. В основе подхода лежит идея разделения геометрии на базовую модель (geometry) и набор инстансов (instances), каждый из которых переопределяет только параметры трансформации и визуальные атрибуты.
В классическом WebGL без инстансинга каждый объект сцены требует отдельного набора вершинных данных или отдельного draw call. Это приводит к узкому месту на CPU из-за частых вызовов отрисовки.
Instanced rendering решает эту проблему за счёт использования расширений:
ANGLE_instanced_arrays (WebGL 1.0)drawArraysInstanced и
drawElementsInstanced (WebGL 2.0)Ключевая идея:
GPU получает базовый меш один раз и применяет его к множеству трансформаций.
Deck.gl строит instanced rendering поверх концепции Layer. Каждый слой определяет:
Типичный слой с инстансингом хранит данные в следующем виде:
Каждый элемент массива данных соответствует одному инстансу.
В Deck.gl атрибуты делятся на два уровня:
Используются внутри базовой модели:
Применяются ко всему объекту:
instancePositions)instanceColors)instanceSizes)instanceAngles)Каждый инстанс получает собственный набор этих параметров, которые
передаются в vertex shader через attribute divisor = 1.
Типичный instanced layer в Deck.gl состоит из трёх компонентов:
import {Layer} from '@deck.gl/core';
import {Model, Geometry} from '@luma.gl/core';
class InstancedExampleLayer extends Layer {
initializeState() {
this.state = {
model: this._getModel()
};
this.state.model.setInstanceCount(this.props.data.length);
}
_getModel() {
return new Model(this.context.device, {
geometry: new Geometry({
attributes: {
positions: new Float32Array([
-1, -1,
1, -1,
1, 1,
-1, 1
])
}
}),
vertexShader: `...`,
fragmentShader: `...`
});
}
}
Deck.gl использует систему AttributeManager для автоматического обновления GPU-буферов.
При изменении data:
bufferDataЭто позволяет избежать полной перезагрузки сцены при каждом обновлении данных.
Особенно важно:
В instanced rendering vertex shader выполняет два уровня трансформации:
Пример логики:
attribute vec3 positions;
attribute vec3 instancePositions;
attribute vec3 instanceColors;
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
varying vec3 vColor;
void main() {
vec3 pos = positions + instancePositions;
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
vColor = instanceColors;
}
В реальных слоях Deck.gl используется более сложная схема с матрицами трансформации:
Для 3D объектов часто используется полноценная матрица 4x4:
Это позволяет представлять каждый инстанс как независимый объект в пространстве.
Преимущество:
Недостаток:
Instanced rendering лежит в основе большинства высокопроизводительных слоёв:
Каждая точка — отдельный инстанс.
Вертикальные столбцы:
Иконки как instanced quads:
Инстансинг используется для каждого гексагона, включая агрегацию данных на GPU.
Ключевые оптимизации instanced rendering в Deck.gl:
Все данные передаются как:
Float32ArrayUint8ArrayInt32ArrayЭто снижает overhead сериализации.
Обновляются только изменённые атрибуты:
Deck.gl поддерживает бинарный формат данных, позволяющий:
Интерактивность реализуется через picking:
Каждый инстанс получает уникальный identifier:
instanceIdПри рендере в picking buffer:
Это позволяет:
Основные факторы ускорения:
Типичная производительность:
Несмотря на эффективность, instanced rendering имеет ограничения:
Deck.gl часто комбинирует instanced rendering с:
Особенно эффективно сочетание instancing с:
Deck.gl позволяет модифицировать шейдеры через injection hooks:
vs:#declvs:#main-startfs:#main-endЭто даёт возможность:
Пример динамического смещения:
pos.z += sin(uTime + instancePositions.x * 0.1) * 5.0;
На уровне архитектуры instanced rendering занимает центральное место:
Именно это разделение позволяет Deck.gl масштабироваться от сотен до миллионов объектов без изменения пользовательского кода.