Отрисовка HTML в холсте WebGPU дает те же преимущества, что и в холсте WebGL, например позволяет применять эффекты шейдеров к DOM или интегрировать интерактивный HTML в 3D-сцены. Однако WebGPU имеет значительные преимущества по сравнению с WebGL.
В этом руководстве показано, как отрисовать HTML на холсте WebGPU. Подробнее об HTML-in-Canvas в обзоре API…
Для рендеринга HTML на холсте WebGPU необходимо выполнить следующие шаги:
- Подготовьте холст. Задайте нужные атрибуты, чтобы браузер знал, что HTML-код нужно отрисовать в элементе canvas. Эта настройка одинакова для контекстов 2D, WebGL и WebGPU. Узнайте, как настроить холст и как объявить элементы HTML, которые будут отрисовываться независимо.
- Примените HTML-код в качестве текстуры:
- Предварительно выделяйте хранилище текстур графического процессора.
- Загрузите снимок DOM в качестве текстуры.
- Синхронизируйте DOM и пиксели.
Отрисовка элемента HTML в качестве текстуры WebGPU
В WebGPU элементы HTML загружаются в графический процессор как 2D-текстуры с помощью drawElementImageToTexture().
Предварительно выделяйте хранилище для текстур
WebGPU требует явного выделения памяти. Прежде чем копировать пиксели DOM в текстуру, необходимо зарезервировать видеопамять графического процессора с помощью метода device.createTexture():
const context = canvas.getContext("webgpu");
// Pre-allocate the texture size as needed
// For example: HTML element CSS size × devicePixelRatio
const size = canvas.getElementImageDefaultSize(myElement);
const myElementWidth = Math.ceil(size.width);
const myElementHeight = Math.ceil(size.height);
// Pre-allocate the GPUTexture backing (run once during setup)
const myTexture = device.createTexture({
size: {
width: myElementWidth,
height: myElementHeight,
depthOrArrayLayers: 1, // optional (defaults to 1)
},
format: "rgba8unorm",
usage:
GPUTextureUsage.TEXTURE_BINDING |
GPUTextureUsage.COPY_DST |
GPUTextureUsage.RENDER_ATTACHMENT,
});
Нарисовать изображение элемента HTML
В WebGPU метод drawElementImageToTexture() рисует снимок элемента HTML. Метод принимает два объекта словаря: source и destination.
source определяет исходный элемент DOM для растеризации и необязательные координаты обрезки подпрямоугольника, которые позволяют скопировать в текстуру только часть элемента, а не весь узел DOM:
| Свойство | Тип | Описание |
|---|---|---|
source (обязательно) |
Element или ElementImage |
Целевой элемент DOM (или предварительно захваченный экземпляр ElementImage), который нужно отрисовать в текстуре. |
sourceX необязательно (все четыре или ни одного) |
число с плавающей запятой | Горизонтальное смещение по оси X (в пикселях CSS), определяющее верхний левый угол исходного фрагмента. |
sourceY – необязательный (все четыре или ни одного) |
число с плавающей запятой | Вертикальное смещение по оси Y (в пикселях CSS), определяющее верхний левый угол исходного фрагмента. |
sourceWidth необязательно (все четыре или ни одного) |
число с плавающей запятой | Ширина (в пикселях CSS) исходного прямоугольника, который нужно обрезать и растрировать. |
sourceHeight необязательно (все четыре или ни одного) |
число с плавающей запятой | Высота (в пикселях CSS) исходного прямоугольника, который нужно обрезать и растрировать. |
destination определяет целевую текстуру графического процессора, которая получает отрисованный снимок DOM, а также необязательные смещения назначения, уровни MIP и размеры копирования для размещения пикселей в определенной области текстуры:
| Свойство | Тип | Описание |
|---|---|---|
texture (обязательно) |
GPUTexture |
Предварительно выделенная целевая текстура WebGPU, которая получит отрисованный пиксельный снимок DOM. |
Необязательных вопросов: size |
GPUExtent3D |
Ширина и высота (в пикселях физической текстуры, например { width, height }) для масштабирования и растеризации элемента в целевой текстуре. |
Необязательных вопросов: origin |
GPUOrigin3D |
Трехмерное смещение (x, y, z) в текстуре, куда будут записаны растрированные пиксели. Значение по умолчанию – [0, 0, 0]. |
Необязательных вопросов: mipLevel |
GPUIntegerCoordinate |
Определенный уровень MIP-текстурирования целевой текстуры, в которую нужно выполнить запись. Значение по умолчанию – 0. |
Необязательных вопросов: aspect |
GPUTextureAspect |
Указывает, какой аспект текстуры копировать ("all", "stencil-only" или "depth-only"). По умолчанию используется "all". |
Необязательных вопросов: colorSpace |
PredefinedColorSpace |
Целевое цветовое пространство (например, "srgb", "display-p3") для преобразования цвета при загрузке. Значение по умолчанию – "srgb". |
Необязательных вопросов: premultipliedAlpha |
Логическое значение | Указывает, нужно ли предварительно умножать альфа-канал на цветовые каналы при загрузке. Значение по умолчанию – false. |
Загрузите элемент в текстуру в событии paint, вызвав метод drawElementImageToTexture():
canvas.addEventListener("paint", (event) => {
const sourceDict = {
source: myElement,
// Optional sub-rectangle crop in CSS pixels
// (defaults to full element if omitted):
sourceX: 0,
sourceY: 0,
sourceWidth: myElement.offsetWidth,
sourceHeight: myElement.offsetHeight,
};
const destDict = {
texture: myTexture,
size: { width: myElementWidth, height: myElementHeight },
};
// Upload the latest DOM snapshot into the pre-allocated GPUTexture
device.queue.drawElementImageToTexture(sourceDict, destDict);
});
Синхронизировать геометрию
Чтобы выровнять проверку нажатия DOM и кольца фокуса специальных возможностей с отрисованным выводом canvas, создайте преобразование DOMMatrix и примените его с помощью метода updateElementGeometry():
// Construct a transform as needed in CSS pixels
// relative to the canvas, for example:
// 1/8 of the canvas width from the left edge, vertically centered.
// scaleX, scaleY: canvas grid pixels per CSS pixel (from resize observer)
const canvasCssWidth = canvas.width / scaleX;
const canvasCssHeight = canvas.height / scaleY;
const elementCssHeight = canvas.getElementImageDefaultSize(myElement).height / scaleY;
const x = canvasCssWidth / 8;
const y = (canvasCssHeight - elementCssHeight) / 2;
const transform = new DOMMatrix().translate(x, y);
// Synchronize the element's DOM hit-testing and accessibility geometry
canvas.updateElementGeometry(myElement, { canvasTransform: transform });
Дальнейшие действия
- Изучите основные технические концепции HTML-in-Canvas.
- Подробнее о том, как отрисовывать HTML в контексте 2D…
- Узнайте, как отрисовывать HTML на холсте WebGL.
- Подробнее о резервных стратегиях…
- Чтобы поделиться отзывом, создайте проблему на GitHub.
- Посмотрите коллекцию демонстраций HTML-in-Canvas от сообщества.