WebGPU 캔버스 내에서 HTML을 렌더링하면 DOM에 셰이더 효과를 적용하거나 대화형 HTML을 3D 장면에 통합하는 등 WebGL 캔버스의 HTML이 제공하는 모든 이점을 누릴 수 있습니다. 하지만 WebGPU는 WebGL에 비해 상당한 이점을 제공합니다.
이 가이드에서는 HTML을 WebGPU 캔버스로 렌더링하는 방법을 보여줍니다. API 개요에서 HTML-in-Canvas에 대해 자세히 알아보세요.
WebGPU 캔버스에서 HTML을 렌더링하려면 다음 단계를 거쳐야 합니다.
- 캔버스를 준비합니다. 브라우저가 HTML을 캔버스에 렌더링해야 한다는 것을 알 수 있도록 올바른 속성을 선언적으로 설정합니다. 이 설정은 2D, WebGL, WebGPU 컨텍스트에서 동일합니다. 캔버스를 설정하는 방법과 독립적으로 그려질 HTML 요소를 선언하는 방법을 알아보세요.
- HTML을 텍스처로 적용합니다.
- GPU 텍스처 스토리지를 미리 할당합니다.
- DOM 스냅샷을 텍스처로 업로드합니다.
- DOM과 픽셀을 동기화합니다.
HTML 요소를 WebGPU 텍스처로 그리기
WebGPU에서 HTML 요소는 drawElementImageToTexture()를 사용하여 2D 텍스처로 GPU에 업로드됩니다.
텍스처 저장소 사전 할당
WebGPU에는 명시적인 메모리 할당이 필요합니다. DOM 픽셀을 텍스처에 복사하기 전에 device.createTexture() 메서드를 사용하여 GPU VRAM을 예약해야 합니다.
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 선택사항 (4개 모두 또는 없음) |
float | 소스 하위 직사각형 슬라이스의 왼쪽 상단을 정의하는 가로 X 좌표 오프셋 (CSS 픽셀)입니다. |
sourceY 선택사항 (4개 모두 또는 없음) |
float | 소스 하위 직사각형 슬라이스의 왼쪽 상단을 정의하는 세로 Y 좌표 오프셋 (CSS 픽셀)입니다. |
sourceWidth 선택사항 (4개 모두 또는 없음) |
float | 자르고 래스터화할 소스 하위 직사각형의 너비 (CSS 픽셀)입니다. |
sourceHeight 선택사항 (4개 모두 또는 없음) |
float | 자르고 래스터화할 소스 하위 직사각형의 높이 (CSS 픽셀)입니다. |
destination는 렌더링된 DOM 스냅샷을 수신하는 타겟 GPU 텍스처를 정의하며, 선택적 대상 오프셋, MIP 수준, 복사 크기를 사용하여 픽셀을 텍스처의 특정 영역에 배치합니다.
| 속성 | 유형 | 설명 |
|---|---|---|
texture이 필요함 |
GPUTexture |
렌더링된 DOM 픽셀 스냅샷을 수신할 사전 할당된 대상 WebGPU 텍스처입니다. |
선택 size개 |
GPUExtent3D |
대상 텍스처 내에서 요소의 크기를 조정하고 래스터화하는 너비와 높이 (실제 텍스처 픽셀, 예: { width, height })입니다. |
선택 origin개 |
GPUOrigin3D |
래스터화된 픽셀이 기록될 텍스처 내의 3D 대상 오프셋 (x, y, z)입니다. 기본값은 [0, 0, 0]입니다. |
선택 mipLevel개 |
GPUIntegerCoordinate |
쓸 대상 텍스처의 특정 밉맵 수준입니다. 기본값은 0입니다. |
선택 aspect개 |
GPUTextureAspect |
복사할 텍스처 관점 ("all", "stencil-only" 또는 "depth-only")을 지정합니다. 기본값은 "all"입니다. |
선택 colorSpace개 |
PredefinedColorSpace |
업로드 시 색상 변환을 위한 대상 색상 공간 (예: "srgb", "display-p3")입니다. 기본값은 "srgb"입니다. |
선택 premultipliedAlpha개 |
부울 | 업로드 중에 알파를 색상 채널에 미리 곱해야 하는지 여부입니다. 기본값은 false입니다. |
drawElementImageToTexture() 메서드를 호출하여 paint 이벤트 내의 텍스처에 요소를 업로드합니다.
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 Hit Test 및 접근성 포커스 링을 렌더링된 캔버스 출력과 정렬하려면 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의 핵심 기술 개념을 이해합니다.
- 2D 컨텍스트에서 HTML을 렌더링하는 방법을 알아보세요.
- WebGL 캔버스에서 HTML을 렌더링하는 방법을 알아보세요.
- 대체 전략 알아보기
- GitHub에서 문제를 제출하여 의견을 공유하세요.
- 커뮤니티의 HTML-in-Canvas 데모 모음을 확인하세요.