واقعیت مجازی به وب می آید

چند نکته‌ی اساسی برای آماده‌سازی شما برای طیف وسیعی از تجربیات فراگیر: واقعیت مجازی، واقعیت افزوده و هر آنچه بین این دو قرار دارد.

جو مدلی
Joe Medley

تجربه‌های فراگیر در کروم ۷۹ به وب آمدند. رابط برنامه‌نویسی کاربردی دستگاه WebXR، واقعیت مجازی را به ارمغان می‌آورد، در حالی که پشتیبانی از واقعیت افزوده در کروم ۸۱ از راه می‌رسد. در حالی که به‌روزرسانی رابط برنامه‌نویسی کاربردی گیم‌پد، استفاده پیشرفته از کنترل‌ها را به واقعیت مجازی گسترش می‌دهد. مرورگرهای دیگر نیز به زودی از این مشخصات پشتیبانی خواهند کرد، از جمله فایرفاکس ریالیتی، مرورگر آکیولس، اج و مرورگر هلیو مجیک لیپ و غیره.

این مقاله، آغازگر مجموعه‌ای از مقالات در مورد وب فراگیر است. این بخش، راه‌اندازی یک برنامه‌ی پایه‌ی WebXR و همچنین ورود و خروج از یک جلسه‌ی XR را پوشش می‌دهد. مقالات بعدی، حلقه‌ی فریم (محرک اصلی تجربه‌ی WebXR)، ویژگی‌های واقعیت افزوده و API تست برخورد WebXR، ابزاری برای تشخیص سطوح در یک جلسه‌ی AR، را پوشش خواهند داد. مگر اینکه خلاف آن ذکر شده باشد، هر آنچه که در این مقاله و مقالات بعدی پوشش می‌دهم، به طور یکسان برای AR و VR نیز صدق می‌کند.

وب فراگیر چیست؟

اگرچه ما از دو اصطلاح برای توصیف تجربیات غوطه‌وری استفاده می‌کنیم - واقعیت افزوده و واقعیت مجازی - بسیاری آنها را در طیفی از واقعیت کامل تا کاملاً مجازی، با درجات غوطه‌وری در بین آنها، در نظر می‌گیرند. 'X' در XR با هدف انعکاس این طرز فکر به عنوان نوعی متغیر جبری که نمایانگر هر چیزی در طیف تجربیات غوطه‌وری است، در نظر گرفته شده است.

نموداری که طیف تجربیات بصری را از واقعیت کامل تا کاملاً فراگیر نشان می‌دهد.
طیف تجربیات فراگیر

نمونه‌هایی از تجربیات فراگیر عبارتند از:

  • بازی‌ها
  • ویدیوهای ۳۶۰ درجه
  • ویدیوهای سنتی دوبعدی (یا سه‌بعدی) که در محیطی فراگیر ارائه می‌شوند
  • خرید خانه
  • مشاهده محصولات در منزل شما قبل از خرید آنها
  • هنر فراگیر
  • یه چیز باحال که هنوز به ذهن هیچ‌کس نرسیده

مفاهیم و کاربردها

من چند نکته‌ی اساسی در مورد استفاده از WebXR Device API را توضیح خواهم داد. اگر به اطلاعات عمیق‌تری نسبت به آنچه ارائه دادم نیاز دارید، نمونه‌های WebXR گروه کاری Immersive Web یا منابع مرجع رو به رشد MDN را بررسی کنید. اگر با نسخه‌های اولیه‌ی WebXR Device API آشنا هستید، باید نگاهی اجمالی به تمام این منابع بیندازید. تغییراتی ایجاد شده است.

کد این مقاله بر اساس نمونه اولیه گروه کاری Immersive Web Working Group ( demo ، source ) است، اما برای وضوح و سادگی ویرایش شده است.

بخشی از ایجاد مشخصات WebXR، بسط و توسعه اقدامات امنیتی و حریم خصوصی برای محافظت از کاربران بوده است. در نتیجه، پیاده‌سازی‌ها باید الزامات خاصی را رعایت کنند. یک صفحه وب یا برنامه قبل از اینکه بتواند هر چیز حساسی را از بیننده درخواست کند، باید فعال و متمرکز باشد. صفحات وب یا برنامه‌ها باید از طریق HTTPS ارائه شوند. خود API برای محافظت از اطلاعات به دست آمده از حسگرها و دوربین‌ها طراحی شده است که برای عملکرد خود به آنها نیاز دارد.

درخواست جلسه

ورود به یک جلسه XR نیاز به یک حرکت کاربر دارد. برای دریافت آن، از تشخیص ویژگی برای آزمایش XRSystem (از طریق navigator.xr ) استفاده کنید و XRSystem.isSessionSupported() را فراخوانی کنید. توجه داشته باشید که در نسخه‌های ۷۹ و ۸۰ کروم، شیء XRSystem با نام XR شناخته می‌شد.

در مثال زیر، من مشخص کرده‌ام که یک جلسه واقعیت مجازی با نوع جلسه 'immersive-vr' می‌خواهم. انواع دیگر جلسه عبارتند از 'immersive-ar' و 'inline' . یک جلسه درون خطی برای ارائه محتوا در HTML است و عمدتاً برای محتوای تیزر استفاده می‌شود. نمونه جلسه Immersive AR این را نشان می‌دهد. من این را در مقاله بعدی توضیح خواهم داد.

وقتی مطمئن شدم که جلسات واقعیت مجازی پشتیبانی می‌شوند، دکمه‌ای را فعال می‌کنم که به من امکان می‌دهد یک ژست کاربر را دریافت کنم.

if (navigator.xr) {
  const supported = await navigator.xr.isSessionSupported('immersive-vr');
  if (supported) {
    xrButton.addEventListener('click', onButtonClicked);
    xrButton.textContent = 'Enter VR';
    xrButton.enabled = supported; // supported is Boolean
  }
}

بعد از فعال کردن دکمه، منتظر یک رویداد کلیک می‌مانم و سپس درخواست یک جلسه (session) می‌دهم.

let xrSession = null;
function onButtonClicked() {
  if (!xrSession) {
    navigator.xr.requestSession('immersive-vr')
    .then((session) => {
      xrSession = session;
      xrButton.textContent = 'Exit XR';
      onSessionStarted(xrSession);
    });
  } else {
    xrSession.end();
  }
}

به سلسله مراتب شیء در این کد توجه کنید. از navigator به xr سپس به یک نمونه XRSession منتقل می‌شود. در نسخه‌های اولیه API، یک اسکریپت قبل از درخواست یک session باید یک دستگاه را درخواست می‌کرد. اکنون، دستگاه به طور ضمنی دریافت می‌شود.

وارد یک جلسه شوید

بعد از دریافت یک session، باید آن را شروع کنم و وارد آن شوم. اما ابتدا باید چند چیز را تنظیم کنم. یک session به یک کنترل‌کننده رویداد onend نیاز دارد تا برنامه یا صفحه وب بتواند پس از خروج کاربر، ریست شود.

همچنین به یک عنصر <canvas> برای ترسیم صحنه‌ام نیاز دارم. این عنصر باید یک WebGLRenderingContext یا WebGL2RenderingContext سازگار با XR باشد. تمام ترسیمات با استفاده از آنها یا یک چارچوب مبتنی بر WebGL مانند Three.js انجام می‌شود.

حالا که جایی برای طراحی دارم، به یک منبع محتوا نیاز دارم تا روی آن طراحی کنم. برای این کار، یک نمونه از XRWebGLLayer ایجاد می‌کنم. آن را با فراخوانی XRSession.updateRenderState() به بوم مرتبط می‌کنم.

وقتی در یک جلسه هستم، به روشی برای تعیین محل چیزها در واقعیت مجازی نیاز دارم. به یک فضای مرجع نیاز دارم. فضای مرجع 'local-floor' فضایی است که مبدا در نزدیکی بیننده قرار دارد و محور y در سطح طبقه 0 است و انتظار نمی‌رود حرکت کند. انواع دیگری از فضاهای مرجع وجود دارد، اما موضوع پیچیده‌تری از آن است که بتوانم در اینجا به آن بپردازم. من فضای مرجع را در یک متغیر ذخیره می‌کنم زیرا هنگام ترسیم روی صفحه به آن نیاز خواهم داشت.

function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);

  let canvas = document.createElement('canvas');
  webGLRenContext = canvas.getContext('webgl', { xrCompatible: true });

  xrSession.updateRenderState({
    baseLayer: new XRWebGLLayer(xrSession, webGLRenContext)
  });

  xrSession.requestReferenceSpace('local-floor')
  .then((refSpace) => {
    xrRefSpace = refSpace;
    xrSession.requestAnimationFrame(onXRFrame);
  });
}

بعد از دریافت فضای مرجع، تابع XRSession.requestAnimationFrame() را فراخوانی می‌کنم. این شروع ارائه محتوای مجازی است که در حلقه فریم انجام می‌شود.

اجرای یک حلقه فریم

حلقه فریم یک حلقه نامحدود است که توسط عامل کاربر کنترل می‌شود و در آن محتوا به طور مکرر روی صفحه نمایش داده می‌شود. محتوا در بلوک‌های گسسته‌ای به نام فریم رسم می‌شود. توالی فریم‌ها باعث ایجاد توهم حرکت می‌شود. برای برنامه‌های واقعیت مجازی، فریم‌ها در هر ثانیه می‌توانند از ۶۰ تا ۱۴۴ باشند. واقعیت افزوده برای اندروید با سرعت ۳۰ فریم در ثانیه اجرا می‌شود. کد شما نباید هیچ نرخ فریم خاصی را در نظر بگیرد.

فرآیند اساسی برای حلقه فریم به شرح زیر است:

  1. فراخوانی XRSession.requestAnimationFrame() . در پاسخ، عامل کاربر XRFrameRequestCallback را که توسط شما تعریف شده است، فراخوانی می‌کند.
  2. درون تابع فراخوانی شما:
    1. دوباره XRSession.requestAnimationFrame() را فراخوانی کنید.
    2. ژست بیننده را بگیرید.
    3. WebGLFramebuffer را از XRWebGLLayer به WebGLRenderingContext ارسال ('bind') کنید.
    4. روی هر شیء XRView تکرار کنید، XRViewport آن را از XRWebGLLayer بازیابی کنید و آن را به WebGLRenderingContext ارسال کنید.
    5. چیزی را در فریم‌بافر رسم کن.

ادامه‌ی این مقاله مرحله‌ی ۱ و بخشی از مرحله‌ی ۲، یعنی راه‌اندازی و فراخوانی XRFrameRequestCallback را شرح می‌دهد. موارد باقی‌مانده از مرحله‌ی ۲ در بخش دوم پوشش داده شده‌اند.

فراخوانی XRFrameRequest

تابع XRFrameRequestCallback توسط شما تعریف می‌شود. این تابع دو پارامتر می‌گیرد: یک DOMHighResTimeStamp و یک نمونه XRFrame . شیء XRFrame اطلاعات مورد نیاز برای رندر کردن یک فریم واحد به صفحه نمایش را فراهم می‌کند. آرگومان DOMHighResTimeStamp برای استفاده‌های بعدی است.

قبل از انجام هر کار دیگری، می‌خواهم فریم انیمیشن بعدی را درخواست کنم. همانطور که قبلاً گفته شد، زمان‌بندی فریم‌ها توسط عامل کاربر بر اساس سخت‌افزار زیربنایی تعیین می‌شود. درخواست فریم بعدی ابتدا تضمین می‌کند که اگر در طول فراخوانی خطایی رخ دهد، حلقه فریم ادامه یابد.

function onXRFrame(hrTime, xrFrame) {
  let xrSession = xrFrame.session;
  xrSession.requestAnimationFrame(onXRFrame);
  // Render a frame.
}

در این مرحله، وقت آن است که چیزی برای بیننده ترسیم کنیم. این بحثی است که باید در بخش دوم به آن بپردازیم. قبل از رفتن به آنجا، اجازه دهید به شما نشان دهم که چگونه یک جلسه را به پایان برسانید.

جلسه را تمام کنید

یک جلسه فراگیر ممکن است به دلایل مختلفی از جمله پایان یافتن توسط کد خودتان از طریق فراخوانی XRSession.end() پایان یابد. دلایل دیگر شامل قطع شدن هدست یا به دست گرفتن کنترل آن توسط برنامه دیگری است. به همین دلیل است که یک برنامه با رفتار مناسب باید رویداد end را رصد کند. وقتی این اتفاق افتاد، جلسه و اشیاء رندر مرتبط با آن را کنار بگذارید. یک جلسه فراگیر پایان یافته را نمی‌توان از سر گرفت. برای ورود مجدد به تجربه فراگیر، برنامه من باید یک جلسه جدید را شروع کند.

از بخش «ورود به یک جلسه» به یاد بیاورید که در طول راه‌اندازی، یک کنترل‌کننده رویداد onend اضافه کردم.

function onSessionStarted(xrSession) {
  xrSession.addEventListener('end', onSessionEnded);
  // More setup…
}

درون کنترل‌کننده‌ی رویداد، وضعیت برنامه را قبل از ورود کاربر به جلسه بازیابی کنید.

function onSessionEnded(event) {
  xrSession = null;
  xrButton.textContent = 'Enter VR';
}

نتیجه‌گیری

من همه چیزهایی را که برای نوشتن یک برنامه Web XR یا AR نیاز دارید توضیح نداده‌ام. امیدوارم به اندازه کافی به شما داده باشم تا بتوانید کد را برای خودتان درک کنید و به اندازه کافی برای شروع آزمایش، اطلاعات کسب کنید. در مقاله بعدی، حلقه فریم را توضیح خواهم داد، جایی که محتوا به صفحه نمایش کشیده می‌شود.