‫HTML في لوحة WebGPU

يوفّر عرض HTML داخل لوحة WebGPU جميع مزايا HTML في لوحة WebGL، مثل تطبيق تأثيرات التظليل على DOM أو دمج HTML التفاعلي في المشاهد الثلاثية الأبعاد. ومع ذلك، يقدّم WebGPU مزايا كبيرة مقارنةً بـ WebGL.

يوضّح هذا الدليل كيفية عرض HTML في لوحة WebGPU. مزيد من المعلومات حول HTML-in-Canvas في نظرة عامة على واجهة برمجة التطبيقات

يتطلّب عرض HTML في لوحة WebGPU اتّباع الخطوات التالية:

  1. جهِّز لوحتك. يمكنك ضبط السمات المناسبة بشكل تعريفي لإعلام المتصفّح بأنّه يجب عرض HTML في لوحة رسم. هذا الإعداد متطابق في سياقات 2D وWebGL وWebGPU. تعرَّف على كيفية إعداد لوحة الرسم وكيفية تحديد عناصر HTML ليتم رسمها بشكل مستقل.
  2. طبِّق رمز HTML كبنية:
    1. تخصيص مساحة تخزين مسبقًا لنسيج وحدة معالجة الرسومات
    2. تحميل لقطة DOM كزخرفة
  3. مزامنة نموذج DOM ووحدات البكسل

رسم عنصر HTML كبنية WebGPU

في WebGPU، يتم تحميل عناصر HTML إلى وحدة معالجة الرسومات كزخارف ثنائية الأبعاد باستخدام drawElementImageToTexture().

تخصيص مساحة تخزين مسبقًا للزخارف

تتطلّب WebGPU تخصيص الذاكرة بشكل صريح. قبل نسخ وحدات بكسل DOM إلى مادة عرض، يجب حجز ذاكرة VRAM لوحدة معالجة الرسومات باستخدام الطريقة 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 اختيارية (كلها أو لا شيء منها) عدد عائم تمثّل هذه السمة الإزاحة الأفقية للإحداثي السيني (بالبكسل في 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 مستوى mipmap المحدّد لنسيج الوجهة المطلوب الكتابة فيه القيمة التلقائية هي 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 وحلقات التركيز على تسهيل الاستخدام مع مخرجات لوحة الرسم المعروضة، أنشئ تحويلاً 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 });

الخطوات التالية