WebGL ক্যানভাসে HTML

WebGL ক্যানভাসে HTML রেন্ডার করার মাধ্যমে আপনি লাইভ DOM সাবট্রিকে ডায়নামিক GPU টেক্সচার হিসেবে ব্যবহার করতে, লাইভ DOM-এ শেডার এফেক্ট প্রয়োগ করতে এবং 3D দৃশ্যে ইন্টার‍্যাক্টিভ HTML ইন্টিগ্রেট করতে পারবেন।

WebGL ক্যানভাসে কীভাবে HTML রেন্ডার করতে হয় তা এই নির্দেশিকা থেকে জানতে পারবেন। API ওভারভিউ থেকে Canvas-এ-HTML সম্পর্কে আরও জানুন।

WebGL ক্যানভাসে HTML রেন্ডার করার জন্য নিম্নলিখিত ধাপগুলি অনুসরণ করতে হবে:

  1. আপনার ক্যানভাস প্রস্তুত করুন। ব্রাউজারকে জানানোর জন্য সঠিক অ্যাট্রিবিউট সেট করুন যাতে এটি ক্যানভাসে HTML রেন্ডার করতে পারে। এই সেট-আপ 2D, WebGL ও WebGPU কন্টেক্সট জুড়ে একই রকম। কীভাবে আপনার ক্যানভাস সেট-আপ করবেন এবং কীভাবে স্বতন্ত্রভাবে আঁকার জন্য HTML এলিমেন্ট ঘোষণা করবেন তা জানুন।
  2. টেক্সচার হিসেবে HTML প্রয়োগ করুন:
    1. GPU টেক্সচার স্টোরেজ আগে থেকে বরাদ্দ করুন।
    2. টেক্সচার হিসেবে DOM স্ন্যাপশট আপলোড করুন।
  3. DOM ও পিক্সেল সিঙ্ক করুন।

WebGL টেক্সচার হিসেবে HTML এলিমেন্ট আঁকা

WebGL-এ, texElementSubImage2D() ব্যবহার করে HTML এলিমেন্ট GPU-তে 2D টেক্সচার হিসেবে আপলোড করা হয়।

টেক্সচার স্টোরেজ আগে থেকে বরাদ্দ করুন

2D ক্যানভাস, যা অটোমেটিক ব্যাকআপ মেমরি ম্যানেজ করে, তার থেকে আলাদা, WebGL কনটেক্সটের জন্য এক্সপ্লিসিট মেমরি ম্যানেজমেন্ট প্রয়োজন।

DOM পিক্সেল আপলোড করার আগে, আপনাকে অবশ্যই GPU মেমরি প্রি-অ্যালোকেট করতে হবে। এর ফলে, ব্রাউজার দ্রুত সাব-ইমেজ আপডেট করতে পারে এবং এর জন্য GPU মেমরি রি-অ্যালোকেশন করার প্রয়োজন হয় না।

বেছে নেওয়া সাইজ প্যারামিটার এবং srcData-এর সাথে বাফার আগে থেকে বরাদ্দ করুন, যা null-এ সেট করা হয়েছে:

// Only allocate texture backing once
if (!textureBufferAllocated) {
  // Pre-allocate texture backing with pre-determined size.
  gl.texImage2D(
    /* target */ gl.TEXTURE_2D,
    /* level */ 0,
    /* internalformat */ gl.RGBA8,
    /* width */ myElementWidth,
    /* height */ myElementHeight,
    /* border */ 0,
    /* format */ gl.RGBA,
    /* type */ gl.UNSIGNED_BYTE,
    /* srcData */ null
  );

  textureBufferAllocated = true;
}

HTML এলিমেন্টের স্বাভাবিক লেআউট সাইজের সাথে টেক্সচার ম্যাচ করতে, ক্যানভাস গ্রিড পিক্সেলে এর ডিফল্ট সাইজ ফিরিয়ে আনতে canvas.getElementImageDefaultSize() ব্যবহার করুন:

const { width, height } = canvas.getElementImageDefaultSize(myElement);
// Pre-allocate texture backing. Only do this once, or whenever the element
// changes size.
gl.texImage2D(
  /* target */ gl.TEXTURE_2D,
  /* level */ 0,
  /* internalformat */ gl.RGBA8,
  /* width */ Math.ceil(width),
  /* height */ Math.ceil(height),
  /* border */ 0,
  /* format */ gl.RGBA,
  /* type */ gl.UNSIGNED_BYTE,
  /* srcData */ null
);

টেক্সচার হিসেবে DOM স্ন্যাপশট আপলোড করুন

পরবর্তী ধাপ হল, আপনার রেন্ডার লুপ বা paint লিসেনারের মধ্যে টেক্সচারে HTML এলিমেন্ট আপলোড করা।

canvas.onpaint = () => {
  // 1. Pre-allocate texture backing first
  // ...

  // 2. Upload HTML snapshot into the WebGL texture
  gl.texElementSubImage2D(
    /* target  */ gl.TEXTURE_2D,
    /* level   */ 0,
    /* xoffset */ 0,
    /* yoffset */ 0,
    /* element */ myElement // or an ElementImage from `captureElementImage()`
  );

  // ...
};

জ্যামিতি সিঙ্ক্রোনাইজ করুন

2D কন্টেক্সটের মতো নয়, ব্রাউজার অটোমেটিক অনুমান করতে পারে না যে 3D কন্টেক্সটে স্ক্রিনের কোথায় টেক্সচার দেখা যাবে। আপনাকে ম্যানুয়ালি 3D মেশের সাথে DOM হিট-টেস্টিং এবং অ্যাক্সেসিবিলিটি বাউন্ডিং বক্স অ্যালাইন করতে হবে।

এটি করতে, একটি DOMMatrix তৈরি করুন যা এলিমেন্টের বর্ডার বক্সকে তার রেন্ডার করা ক্যানভাস পিক্সেল লোকেশনে ম্যাপ করে, তারপর updateElementGeometry() ব্যবহার করে এটি প্রয়োগ করুন:

canvas.addEventListener("paint", () => {
  // 1. Upload fresh DOM snapshot to GPU texture
  gl.bindTexture(gl.TEXTURE_2D, myTexture);
  gl.texElementSubImage2D(gl.TEXTURE_2D, 0, 0, 0, myElement);

  // 2. Draw your 3D scene
  draw3DScene();

  // 3. Construct the CSS-pixel transform mapping the element's
  // border box to its drawn position on the canvas as needed
  // (for example: scale and translate)
  const canvasTransform = new DOMMatrix();
  // scale X
  canvasTransform.a = canvas.clientWidth / myElement.offsetWidth;
  // scale Y
  canvasTransform.d = canvas.clientHeight / myElement.offsetHeight;
  // translate X (CSS px)
  canvasTransform.e = 50;
  // translate Y (CSS px)
  canvasTransform.f = 100;

  // 4. Update DOM position, accessibility focus rings, and pointer hit-testing
  canvas.updateElementGeometry(myElement, {
    canvasTransform: canvasTransform,
  });
});

পরবর্তী ধাপ