به وب فراگیر خوش آمدید

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

Joe Medley
Joe Medley

وب فراگیر یعنی تجربه‌های دنیای مجازی که ازطریق مرورگر میزبانی می‌شود. این شامل کل تجربه‌های واقعیت مجازی (VR) می‌شود که در مرورگر یا در هدست‌های سازگار با VR مانند Google Daydream،‏ Oculus Rift،‏ Samsung Gear VR،‏ HTC Vive، و هدست‌های واقعیت ترکیبی Windows ظاهر می‌شوند، و همچنین تجربه‌های واقعیت افزوده که برای دستگاه‌های همراه سازگار با AR توسعه یافته‌اند.

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

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

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

چگونه به آنجا بروم؟

وب فراگیر اکنون نزدیک به یک سال است که به‌صورت جنینی دردسترس است. این کار ازطریق WebVR 1.1 API انجام شد که از Chrome 62 در آزمایش معرفی ویژگی جدید دردسترس بوده است. این میانای برنامه‌سازی کاربردی توسط Firefox و Edge و همچنین شبیه‌ساز مرورگر برای Safari پشتیبانی می‌شود.

اما وقت آن است که به چیزهای دیگر بپردازیم.

آزمایش معرفی ویژگی جدید در ۲۴ ژوئیه ۲۰۱۸ به‌پایان رسید و مشخصات با WebXR Device API و آزمایش معرفی ویژگی جدید جایگزین شده است.

چه اتفاقی برای WebVR 1.1 افتاد؟

ما از WebVR 1.1 چیزهای زیادی یاد گرفتیم، اما با گذشت زمان، مشخص شد که برای پشتیبانی از انواع برنامه‌هایی که توسعه‌دهندگان می‌خواهند بسازند، به برخی تغییرات عمده نیاز است. فهرست کامل درس‌های آموخته‌شده بسیار طولانی است که نمی‌توان در اینجا به آن پرداخت، اما شامل مسائلی مانند گره خوردن صریح API به رشته اصلی جاوا اسکریپت، فرصت‌های بسیار زیاد برای توسعه‌دهندگان برای راه‌اندازی پیکربندی‌های آشکارا اشتباه، و استفاده‌های رایج مانند پنجره جادویی که یک اثر جانبی است تا یک ویژگی عمدی. (پنجره جادویی تکنیکی برای مشاهده محتوای فراگیر بدون هدست است که در آن برنامه یک نمای واحد را براساس حسگر جهت دستگاه ارائه می‌دهد.)

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

WebXR Device API با درنظر گرفتن این موارد استفاده گسترده طراحی و نام‌گذاری شده است و مسیر بهتری را برای آینده فراهم می‌کند. پیاده‌سازان WebVR متعهد شده‌اند به WebXR Device API مهاجرت کنند.

WebXR Device API چیست؟

مانند مشخصات WebVR قبل‌از آن، WebXR Device API محصولی از Immersive Web Community Group است که مشارکت‌کنندگانی از Google،‏ Microsoft،‏ Mozilla، و دیگران دارد. حرف «X» در «واقعیت گسترده» (XR) به‌عنوان نوعی متغیر جبری درنظر گرفته می‌شود که نشان‌دهنده هر چیزی در طیف تجربه‌های فراگیر است. این ویژگی در آزمایش معرفی ویژگی جدید که قبلاً ذکر شد و همچنین ازطریق شبیه‌ساز مرورگر دردسترس است.

وقتی این مقاله در ابتدا در دوره Chrome 67 بتا منتشر شد، فقط قابلیت‌های واقعیت مجازی فعال بود. واقعیت افزوده در Chrome 69 ارائه شد. در واقعیت افزوده برای وب درباره آن بخوانید.

این میانای برنامه‌سازی کاربردی جدید چیزهای بیشتری دارد که نمی‌توانم در مقاله‌ای مثل این به آن‌ها بپردازم. می‌خواهم به‌اندازه کافی به شما اطلاعات بدهم تا بتوانید نمونه‌های WebXR را درک کنید. می‌توانید اطلاعات بیشتری را در توضیح‌دهنده اصلی و راهنمای پذیرندگان آغازین وب فراگیر ما پیدا کنید. با پیشرفت آزمایش معرفی ویژگی جدید، مورد دوم را گسترش خواهم داد. می‌توانید مشکلات را باز کنید یا درخواست‌های pull ارسال کنید.

در این مقاله، قصد دارم درباره شروع، توقف، و اجرای جلسه XR و همچنین چند نکته اساسی درباره پردازش ورودی صحبت کنم.

آنچه قرار نیست پوشش دهم نحوه ترسیم محتوای واقعیت افزوده/ واقعیت مجازی روی صفحه است. میانای برنامه‌سازی کاربردی دستگاه WebXR ویژگی‌های پردازش تصویر ارائه نمی‌دهد. به خودتان بستگی دارد. طراحی بااستفاده از میاناهای برنامه‌سازی کاربردی WebGL انجام می‌شود. اگر واقعاً بلندپرواز هستید، می‌توانید این کار را انجام دهید. بااین‌حال، توصیه می‌کنیم از چارچوب استفاده کنید. نمونه‌های وب فراگیر از نمونه‌ای استفاده می‌کنند که فقط برای نسخه‌های نمایشی ایجاد شده است و Cottontail نام دارد. Three.js از ماه مه از WebXR پشتیبانی می‌کند. درباره A-Frame چیزی نشنیده‌ام.

شروع و اجرای برنامه

فرایند اصلی به این صورت است:

  1. درخواست دستگاه XR.
  2. اگر دردسترس بود، درخواست جلسه XR کنید. اگر می‌خواهید کاربر تلفنش را در هدست قرار دهد، به آن جلسه فراگیر گفته می‌شود و برای ورود به آن به اشاره کاربر نیاز است.
  3. از جلسه برای اجرای حلقه رندر که ۶۰ قاب تصویر در ثانیه ارائه می‌دهد استفاده کنید. محتوای مناسب را در هر فریم روی صفحه بکشید.
  4. حلقه پردازش را تا زمانی که کاربر تصمیم به خروج بگیرد اجرا کنید.
  5. جلسه «واقعیت گسترده» را به‌پایان برسانید.

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

درخواست دستگاه XR

در اینجا، کد تشخیص ویژگی استاندارد را تشخیص خواهید داد. می‌توانید این را در تابعی با نامی مثل checkForXR() قرار دهید.

اگر از جلسه فراگیر استفاده نمی‌کنید، می‌توانید از تبلیغ کردن عملکرد و دریافت اشاره کاربر صرف‌نظر کنید و مستقیماً به درخواست جلسه بروید. جلسه فراگیر جلسه‌ای است که به هدست نیاز دارد. جلسه غیرفراگیر به‌سادگی محتوا را در صفحه دستگاه نشان می‌دهد. مورد اول چیزی است که اکثر افراد وقتی به واقعیت مجازی یا واقعیت افزوده اشاره می‌کنید به آن فکر می‌کنند. به دومی گاهی «پنجره جادویی» می‌گویند.

if (navigator.xr) {
    navigator.xr.requestDevice()
    .then(xrDevice => {
    // Advertise the AR/VR functionality to get a user gesture.
    })
    .catch(err => {
    if (err.name === 'NotFoundError') {
        // No XRDevices available.
        console.error('No XR devices available:', err);
    } else {
        // An error occurred while requesting an XRDevice.
        console.error('Requesting XR device failed:', err);
    }
    })
} else{
    console.log("This browser does not support the WebXR API.");
}

درخواست جلسه «واقعیت گسترده»

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

xrPresentationContext = htmlCanvasElement.getContext('xrpresent');
let sessionOptions = {
    // The immersive option is optional for non-immersive sessions; the value
    //   defaults to false.
    immersive: false,
    outputContext: xrPresentationContext
}
xrDevice.requestSession(sessionOptions)
.then(xrSession => {
    // Use a WebGL context as a base layer.
    xrSession.baseLayer = new XRWebGLLayer(session, gl);
    // Start the render loop
})

اجرای حلقه پردازش

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

فرایند اصلی برای حلقه پردازش تصویر این است:

  1. درخواست کردن قاب پویانمایی.
  2. پرس‌وجو برای موقعیت دستگاه.
  3. محتوا را براساس موقعیت دستگاه در موقعیت آن بکشید.
  4. کارهای لازم را برای دستگاه‌های ورودی انجام دهید.
  5. ۶۰ بار در ثانیه تکرار می‌شود تا زمانی که کاربر تصمیم به خروج بگیرد.

درخواست کردن قاب ارائه

کلمه «قاب» در زمینه Web XR چندین معنی دارد. اولی چارچوب مرجع است که تعریف می‌کند مبدأ سیستم مختصات از کجا محاسبه می‌شود و وقتی دستگاه حرکت می‌کند چه اتفاقی برای آن مبدأ می‌افتد. (آیا وقتی کاربر حرکت می‌کند، نما ثابت می‌ماند یا مانند دنیای واقعی تغییر می‌کند؟)

نوع دوم قاب قاب ارائه است که با شیء XRFrame نشان داده می‌شود. این شیء حاوی اطلاعات لازم برای پرداخت یک فریم از صحنه واقعیت مجازی/ واقعیت افزوده در دستگاه است. این کمی گیج‌کننده است زیرا قاب ارائه با فراخوانی requestAnimationFrame() بازیابی می‌شود. این کار آن را با window.requestAnimationFrame() سازگار می‌کند.

قبل‌از اینکه اطلاعات بیشتری برای هضم کردن به شما بدهم، کدی را ارائه خواهم داد. نمونه زیر نشان می‌دهد که حلقه پردازش چطور شروع و حفظ می‌شود. به کاربرد دوگانه کلمه قاب توجه کنید. و به فراخوانی بازگشتی به requestAnimationFrame() توجه کنید. این تابع ۶۰ بار در ثانیه فراخوانی می‌شود.

xrSession.requestFrameOfReference('eye-level')
.then(xrFrameOfRef => {
    xrSession.requestAnimationFrame(onFrame(time, xrFrame) {
    // The time argument is for future use and not implemented at this time.
    // Process the frame.
    xrFrame.session.requestAnimationFrame(onFrame);
    }
});

ژست‌ها

قبل‌از ترسیم هر چیزی روی صفحه‌نمایش، باید بدانید دستگاه نمایشگر به کجا اشاره می‌کند و باید به صفحه‌نمایش دسترسی داشته باشید. به‌طور کلی، موقعیت و جهت یک چیز در واقعیت افزوده/ واقعیت مجازی، «ژست» نامیده می‌شود. هم بینندگان و هم دستگاه‌های ورودی دارای حالت هستند. (بعداً به دستگاه‌های ورودی می‌پردازم.) هر دو حالت بیننده و دستگاه ورودی به‌عنوان یک ماتریس ۴ در ۴ تعریف می‌شوند که در یک Float32Array در ترتیب اصلی ستون ذخیره شده است. با فراخوانی XRFrame.getDevicePose() در شیء فریم پویانمایی فعلی، حالت بیننده را دریافت می‌کنید. همیشه آزمایش کنید تا ببینید آیا ژست را دریافت کرده‌اید یا نه. اگر مشکلی پیش آمد، نمی‌خواهید روی صفحه بکشید.

let pose = xrFrame.getDevicePose(xrFrameOfRef);
if (pose) {
    // Draw something to the screen.
}

بازدیدها

پس‌از بررسی ژست، وقت آن است که چیزی بکشید. شیئی که روی آن طراحی می‌کنید نما (XRView) نامیده می‌شود. اینجا است که نوع جلسه اهمیت پیدا می‌کند. نماها به‌صورت آرایه از شیء XRFrame بازیابی می‌شوند. اگر در جلسه غیرفراگیر هستید، آرایه یک نما دارد. اگر در جلسه فراگیر هستید، آرایه دو عنصر دارد، یکی برای هر چشم.

for (let view of xrFrame.views) {
    // Draw something to the screen.
}

این تفاوت مهمی بین WebXR و دیگر سیستم‌های فراگیر است. اگرچه ممکن است تکرار در یک نما بی‌فایده به‌نظر برسد، اما انجام این کار به شما امکان می‌دهد یک مسیر پردازش واحد برای انواع دستگاه‌ها داشته باشید.

کل حلقه پرداز زدن

اگر همه این‌ها را کنار هم بگذارم، کد زیر را دریافت می‌کنم. من یک جای‌بان برای دستگاه‌های ورودی گذاشته‌ام که در بخش بعدی به آن خواهم پرداخت.

xrSession.requestFrameOfReference('eye-level')
.then(xrFrameOfRef => {
    xrSession.requestAnimationFrame(onFrame(time, xrFrame) {
    // The time argument is for future use and not implemented at this time.
    let pose = xrFrame.getDevicePose(xrFrameOfRef);
    if (pose) {
        for (let view of xrFrame.views) {
        // Draw something to the screen.
        }
    }
    // Input device code will go here.
    frame.session.requestAnimationFrame(onFrame);
    }
}

پایان دادن به جلسه «واقعیت گسترده»

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

xrDevice.requestSession(sessionOptions)
.then(xrSession => {
    // Create a WebGL layer and initialize the render loop.
    xrSession.addEventListener('end', onSessionEnd);
});

// Restore the page to normal after immersive access has been released.
function onSessionEnd() {
    xrSession = null;

    // Ending the session stops executing callbacks passed to the XRSession's
    // requestAnimationFrame(). To continue rendering, use the window's
    // requestAnimationFrame() function.
    window.requestAnimationFrame(onDrawFrame);
}

تعامل چگونه کار می‌کند؟

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

‫WebXR Device API از رویکرد «اشاره و کلیک» برای ورودی کاربر استفاده می‌کند. با این رویکرد، هر منبع ورودی دارای یک پرتو اشاره‌گر تعریف‌شده است که نشان می‌دهد دستگاه ورودی به کجا اشاره می‌کند و رویدادهایی که نشان می‌دهند چه زمانی چیزی انتخاب شده است. برنامه شما پرتو اشاره‌گر را ترسیم می‌کند و نشان می‌دهد به کجا اشاره شده است. وقتی کاربر روی دستگاه ورودی کلیک می‌کند، رویدادها فعال می‌شوند - به‌ویژه select، selectStart، و selectEnd. برنامه شما تعیین می‌کند روی چه چیزی کلیک شده است و به‌طور مناسب پاسخ می‌دهد.

دستگاه ورودی و پرتو اشاره‌گر

برای کاربران، پرتو اشاره‌گر فقط خطی کم‌رنگ بین کنترل‌کننده و چیزی است که به آن اشاره می‌کنند. اما برنامه‌تان باید آن را ترسیم کند. یعنی دریافت ژست دستگاه ورودی و کشیدن خطی از مکان آن به شیء در فضای واقعیت افزوده/ مجازی. این فرایند تقریباً به این صورت است:

let inputSources = xrSession.getInputSources();
for (let xrInputSource of inputSources) {
    let inputPose = frame.getInputPose(inputSource, xrFrameOfRef);
    if (!inputPose) {
    continue;
    }
    if (inputPose.gripMatrix) {
    // Render a virtual version of the input device
    //   at the correct position and orientation.
    }
    if (inputPose.pointerMatrix) {
    // Draw a ray from the gripMatrix to the pointerMatrix.
    }
}

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

انتخاب کردن موارد در فضای مجازی

صرفاً اشاره کردن به چیزها در واقعیت افزوده/ واقعیت مجازی چندان مفید نیست. برای انجام هر کار مفیدی، کاربران باید بتوانند چیزها را انتخاب کنند. WebXR Device API سه رویداد برای پاسخ به تعاملات کاربر ارائه می‌دهد: select، selectStart، و selectEnd. آن‌ها یک ویژگی عجیب دارند که انتظارش را نداشتم: فقط به شما می‌گویند که روی یک دستگاه ورودی کلیک شده است. این داده‌ها به شما نمی‌گویند روی کدام مورد در محیط کلیک شده است. مدیران رویداد به شیء XRSession اضافه می‌شوند و باید به‌محض دردسترس قرار گرفتن اضافه شوند.

xrDevice.requestSession(sessionOptions)
.then(xrSession => {
    // Create a WebGL layer and initialize the render loop.
    xrSession.addEventListener('selectstart', onSelectStart);
    xrSession.addEventListener('selectend', onSelectEnd);
    xrSession.addEventListener('select', onSelect);
});

این کد براساس نمونه انتخاب ورودی است، درصورتی‌که بخواهید بافت بیشتری داشته باشید.

برای اینکه بفهمید روی چه چیزی کلیک شده است، از حالت استفاده می‌کنید. (شگفت‌زده شدید؟ من هم همین‌طور فکر می‌کردم.) جزئیات آن مختص برنامه شما یا هر چارچوبی است که استفاده می‌کنید، بنابراین فراتر از محدوده این مقاله است. رویکرد Cottontail در نمونه «انتخاب ورودی» است.

function onSelect(ev) {
    let inputPose = ev.frame.getInputPose(ev.inputSource, xrFrameOfRef);
    if (!inputPose) {
    return;
    }
    if (inputPose.pointerMatrix) {
    // Figure out what was clicked and respond.
    }
}

نتیجه‌گیری: پیش‌نگری

همان‌طور که قبلاً گفتم، انتظار می‌رود واقعیت افزوده در Chrome 69 (Canary در ژوئن ۲۰۱۸) ارائه شود. بااین‌حال، شما را تشویق می‌کنم آنچه را که تاکنون به‌دست آورده‌ایم امتحان کنید. برای بهتر کردن آن به بازخورد نیاز داریم. با تماشای ChromeStatus.com برای WebXR Hit Test، پیشرفت آن را دنبال کنید. همچنین می‌توانید لنگرهای WebXR را دنبال کنید که ردیابی حالت را بهبود می‌بخشد.