WebGPU कैनवस में एचटीएमएल

WebGPU कैनवस में एचटीएमएल रेंडर करने से, वे सभी फ़ायदे मिलते हैं जो WebGL कैनवस में एचटीएमएल रेंडर करने से मिलते हैं. जैसे, डीओएम पर शेडर इफ़ेक्ट लागू करना या 3D सीन में इंटरैक्टिव एचटीएमएल को इंटिग्रेट करना. हालांकि, WebGL की तुलना में WebGPU के कई फ़ायदे हैं.

इस गाइड में, WebGPU कैनवस में एचटीएमएल को रेंडर करने का तरीका बताया गया है. एपीआई की खास जानकारी में, HTML-in-Canvas के बारे में ज़्यादा जानें.

WebGPU कैनवस में एचटीएमएल रेंडर करने के लिए, यह तरीका अपनाना होगा:

  1. अपना कैनवस तैयार करें. सही एट्रिब्यूट को डिक्लेयर करके सेट करें, ताकि ब्राउज़र को पता चल सके कि उसे एचटीएमएल को कैनवस में रेंडर करना है. यह सेटअप 2D, WebGL, और WebGPU कॉन्टेक्स्ट में एक जैसा होता है. कैनवस सेट अप करने और एचटीएमएल एलिमेंट को अलग-अलग ड्रॉ करने के लिए एलान करने का तरीका जानें.
  2. एचटीएमएल को टेक्सचर के तौर पर लागू करें:
    1. जीपीयू टेक्सचर स्टोरेज को पहले से तय करें.
    2. डीओएम स्नैपशॉट को टेक्स्चर के तौर पर अपलोड करें.
  3. डीओएम और पिक्सल को सिंक करना.

एचटीएमएल एलिमेंट को WebGPU टेक्सचर के तौर पर ड्रॉ करना

WebGPU में, एचटीएमएल एलिमेंट को drawElementImageToTexture() का इस्तेमाल करके, जीपीयू पर 2D टेक्स्चर के तौर पर अपलोड किया जाता है.

टेक्सचर स्टोरेज को पहले से तय करें

WebGPU के लिए, मेमोरी का बंटवारा साफ़ तौर पर करना ज़रूरी है. डीओएम पिक्सल को किसी टेक्सचर में कॉपी करने से पहले, आपको 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,
});

एचटीएमएल एलिमेंट की इमेज ड्रॉ करना

WebGPU में, drawElementImageToTexture() मेथड एचटीएमएल एलिमेंट का स्नैपशॉट ड्रॉ करता है. इस तरीके में दो डिक्शनरी ऑब्जेक्ट इस्तेमाल किए जाते हैं: source और destination.

source, रास्टराइज़ करने के लिए सोर्स डीओएम एलिमेंट और वैकल्पिक सब-रेक्टैंगल क्लिपिंग कोऑर्डिनेट तय करता है. इनकी मदद से, पूरे डीओएम नोड के बजाय एलिमेंट के सिर्फ़ एक हिस्से को अपने टेक्सचर में कॉपी किया जा सकता है:

प्रॉपर्टी टाइप ब्यौरा
source सदस्य ज़रूरी हैं Element या ElementImage टेक्सचर में ड्रॉ करने के लिए, टारगेट डीओएम एलिमेंट (या पहले से कैप्चर किया गया ElementImage इंस्टेंस).
sourceX ज़रूरी नहीं है (सभी चार या कोई नहीं) फ़्लोट हॉरिज़ॉन्टल X-कोऑर्डिनेट ऑफ़सेट (सीएसएस पिक्सल में), जो सोर्स सब-रेक्टैंगल स्लाइस के सबसे ऊपर बाएं कोने को तय करता है.
sourceY ज़रूरी नहीं है (सभी चार या कोई नहीं) फ़्लोट वर्टिकल Y-कोऑर्डिनेट ऑफ़सेट (सीएसएस पिक्सल में), जो सोर्स सब-रेक्टैंगल स्लाइस के सबसे ऊपर बाएं कोने को तय करता है.
sourceWidth ज़रूरी नहीं है (सभी चार या कोई नहीं) फ़्लोट सोर्स सब-रेक्टैंगल की चौड़ाई (सीएसएस पिक्सल में), जिसे काटना और रास्टराइज़ करना है.
sourceHeight ज़रूरी नहीं है (सभी चार या कोई नहीं) फ़्लोट क्रॉप और रास्टराइज़ करने के लिए, सोर्स सब-रेक्टैंगल की ऊंचाई (सीएसएस पिक्सल में).

destination, टारगेट जीपीयू टेक्स्चर को तय करता है. इसमें रेंडर किया गया डीओएम स्नैपशॉट मिलता है. साथ ही, इसमें डेस्टिनेशन ऑफ़सेट, एमआईपी लेवल, और कॉपी डाइमेंशन के विकल्प भी होते हैं. इनकी मदद से, पिक्सल को टेक्स्चर के किसी खास हिस्से में रखा जा सकता है:

प्रॉपर्टी टाइप ब्यौरा
texture सदस्य ज़रूरी हैं GPUTexture पहले से तय किया गया डेस्टिनेशन WebGPU टेक्स्चर, जिसमें रेंडर किया गया DOM पिक्सल स्नैपशॉट मिलेगा.
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);
});

ज्यामिति को सिंक करना

डीओएम हिट-टेस्टिंग और सुलभता फ़ोकस रिंग को रेंडर किए गए कैनवस आउटपुट के साथ अलाइन करने के लिए, 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 });

अगले चरण