फ़्रेम लूप के बारे में सारी जानकारी
हाल ही में, मैंने वर्चुअल रिएलिटी अब वेब पर भी उपलब्ध है लेख पब्लिश किया था. इसमें WebXR Device API के बुनियादी सिद्धांतों के बारे में बताया गया था. मैंने एक्सआर सेशन का अनुरोध करने, उसे शुरू करने, और उसे खत्म करने के निर्देश भी दिए हैं.
इस लेख में फ़्रेम लूप के बारे में बताया गया है. यह एक ऐसा इनफ़िनिट लूप है जिसे उपयोगकर्ता-एजेंट कंट्रोल करता है. इसमें कॉन्टेंट को बार-बार स्क्रीन पर दिखाया जाता है. कॉन्टेंट को अलग-अलग ब्लॉक में बनाया जाता है. इन्हें फ़्रेम कहा जाता है. फ़्रेम के क्रम से, हिलने-डुलने का भ्रम पैदा होता है.
इस लेख में क्या नहीं है
WebXR ऐप्लिकेशन में फ़्रेम लूप के दौरान कॉन्टेंट रेंडर करने के लिए, सिर्फ़ WebGL और WebGL2 का इस्तेमाल किया जा सकता है. अच्छी बात यह है कि कई फ़्रेमवर्क, WebGL और WebGL2 के ऊपर अबस्ट्रैक्शन की लेयर उपलब्ध कराते हैं. ऐसे फ़्रेमवर्क में three.js, babylonjs, और PlayCanvas शामिल हैं. वहीं, A-Frame और React 360 को WebXR के साथ इंटरैक्ट करने के लिए डिज़ाइन किया गया था.
इस लेख में, इमर्सिव वेब वर्किंग ग्रुप के इमर्सिव वीआर सेशन के सैंपल (डेमो, सोर्स) का इस्तेमाल करके, फ़्रेम लूप की बुनियादी बातों के बारे में बताया गया है. अगर आपको WebGL या किसी फ़्रेमवर्क के बारे में ज़्यादा जानना है, तो ऑनलाइन उपलब्ध संसाधनों की सूची लगातार बढ़ती जा रही है.
खिलाड़ी और गेम
फ़्रेम लूप को समझने की कोशिश करते समय, मुझे जानकारी नहीं मिल रही थी. गेम में कई ऑब्जेक्ट हैं. इनमें से कुछ ऑब्जेक्ट के नाम, सिर्फ़ दूसरे ऑब्जेक्ट की रेफ़रंस प्रॉपर्टी के तौर पर दिए गए हैं. इसे समझने में आपकी मदद करने के लिए, मैं ऑब्जेक्ट के बारे में बताऊंगी. इन्हें 'प्लेयर' कहा जाता है. इसके बाद, मैं बताऊंगी कि ये दोनों कैसे इंटरैक्ट करते हैं. इसे 'गेम' कहा जाता है.
खिलाड़ी
XRViewerPose
किसी ऑब्जेक्ट की पोज़िशन और ओरिएंटेशन को 3D स्पेस में पोज़ कहा जाता है. दर्शक और इनपुट डिवाइस, दोनों के पास पोज़ होता है. हालांकि, यहां हम दर्शक के पोज़ के बारे में बात कर रहे हैं. दर्शक और इनपुट डिवाइस, दोनों के पोज़ में transform एट्रिब्यूट होता है. यह एट्रिब्यूट, ओरिजन के हिसाब से पोज़ की पोज़िशन को वेक्टर के तौर पर और ओरिएंटेशन को क्वाटर्नियन के तौर पर दिखाता है. XRSession.requestReferenceSpace() को कॉल करते समय, अनुरोध किए गए रेफ़रंस स्पेस टाइप के आधार पर ऑरिजिन तय किया जाता है.
रेफ़रंस स्पेस के बारे में बताने में थोड़ा समय लगता है. मैंने इनके बारे में ऑगमेंटेड
रियलिटी में विस्तार से बताया है. इस लेख में जिस सैंपल का इस्तेमाल किया गया है उसमें 'local' रेफ़रंस स्पेस का इस्तेमाल किया गया है. इसका मतलब है कि ओरिजन, सेशन बनाते समय व्यूअर की पोज़िशन पर होता है. इसमें फ़्लोर की जानकारी नहीं होती है और इसकी सटीक पोज़िशन, प्लैटफ़ॉर्म के हिसाब से अलग-अलग हो सकती है.
XRView
व्यू, वर्चुअल सीन को देखने वाले कैमरे के हिसाब से होता है. व्यू में transform एट्रिब्यूट भी होता है. यह एट्रिब्यूट, व्यू की पोज़िशन और ओरिएंटेशन के बारे में बताता है.
इन्हें वेक्टर/क्वाटर्नियन पेयर और इक्विवेलेंट मैट्रिक्स, दोनों के तौर पर उपलब्ध कराया जाता है. अपने कोड के हिसाब से, इनमें से किसी भी फ़ॉर्मैट का इस्तेमाल किया जा सकता है. हर व्यू, डिसप्ले या डिसप्ले के उस हिस्से से जुड़ा होता है जिसका इस्तेमाल डिवाइस, दर्शक को इमेज दिखाने के लिए करता है. XRView ऑब्जेक्ट, XRViewerPose ऑब्जेक्ट से एक कलेक्शन में दिखाए जाते हैं. ऐरे में व्यू की संख्या अलग-अलग होती है. मोबाइल डिवाइसों पर, एआर सीन का एक व्यू होता है. यह डिवाइस की स्क्रीन को कवर कर भी सकता है और नहीं भी.
आम तौर पर, हेडसेट में दो व्यू होते हैं. हर आंख के लिए एक व्यू.
XRWebGLLayer
लेयर, बिटमैप इमेज का सोर्स होती हैं. साथ ही, इनमें यह जानकारी होती है कि डिवाइस में उन इमेज को कैसे रेंडर किया जाना है. इस ब्यौरे में, इस प्लेयर के काम करने के तरीके के बारे में पूरी जानकारी नहीं दी गई है. मुझे लगता है कि यह डिवाइस और WebGLRenderingContext के बीच एक बिचौलिए की तरह काम करता है. MDN भी इसी तरह का नज़रिया रखता है. इसके मुताबिक, यह दोनों के बीच 'लिंक उपलब्ध कराता है'. इसलिए, यह अन्य खिलाड़ियों को ऐक्सेस देता है.
आम तौर पर, WebGL ऑब्जेक्ट, 2D और 3D ग्राफ़िक रेंडर करने के लिए, स्थिति की जानकारी सेव करते हैं.
WebGLFramebuffer
फ़्रेमबफ़र, WebGLRenderingContext को इमेज का डेटा उपलब्ध कराता है. XRWebGLLayer से इसे वापस पाने के बाद, इसे मौजूदा WebGLRenderingContext को पास किया जाता है. bindFramebuffer() को कॉल करने के अलावा, आपके पास इस ऑब्जेक्ट को सीधे तौर पर ऐक्सेस करने का कोई और तरीका नहीं है. इसके बारे में हम आपको बाद में ज़्यादा जानकारी देंगे. आपको इसे सिर्फ़ XRWebGLLayer से WebGLRenderingContext में पास करना होगा.
XRViewport
व्यूपोर्ट, WebGLFramebuffer में मौजूद आयताकार क्षेत्र के कोऑर्डिनेट और डाइमेंशन उपलब्ध कराता है.
WebGLRenderingContext
रेंडरिंग कॉन्टेक्स्ट, कैनवस (वह जगह जहां हम ड्रॉ कर रहे हैं) के लिए प्रोग्राम के हिसाब से ऐक्सेस पॉइंट होता है. इसके लिए, इसे WebGLFramebuffer और XRViewport, दोनों की ज़रूरत होती है.
XRWebGLLayer और WebGLRenderingContext के बीच के संबंध पर ध्यान दें. इनमें से एक, दर्शक के डिवाइस के हिसाब से होता है और दूसरा वेब पेज के हिसाब से.
WebGLFramebuffer और XRViewport को पहले से दूसरे में पास किया जाता है.
XRWebGLLayer और WebGLRenderingContext के बीच का संबंध
गेम
अब हमें पता चल गया है कि खिलाड़ी कौन हैं. इसलिए, आइए देखते हैं कि वे कौन-सा गेम खेलते हैं. यह एक ऐसा गेम है जो हर फ़्रेम के साथ फिर से शुरू होता है. याद रखें कि फ़्रेम, फ़्रेम लूप का हिस्सा होते हैं. यह लूप, हार्डवेयर के हिसाब से तय की गई दर पर होता है. वीआर ऐप्लिकेशन के लिए, फ़्रेम प्रति सेकंड की संख्या 60 से 144 तक हो सकती है. Android के लिए AR, 30 फ़्रेम प्रति सेकंड की स्पीड से काम करता है. आपके कोड में, फ़्रेम रेट को लेकर कोई अनुमान नहीं लगाया जाना चाहिए.
फ़्रेम लूप की बुनियादी प्रोसेस कुछ इस तरह दिखती है:
XRSession.requestAnimationFrame()पर कॉल करें. इसके जवाब में, उपयोगकर्ता एजेंटXRFrameRequestCallbackको शुरू करता है. इसे आपने तय किया है.- अपने कॉलबैक फ़ंक्शन में:
XRSession.requestAnimationFrame()पर फिर से कॉल करें.- दर्शक की पोज़ की जानकारी पाना.
XRWebGLLayerसेWebGLFramebufferकोWebGLRenderingContextमें पास ('bind') करें.- हर
XRViewऑब्जेक्ट पर इटरेट करें. इसकेXRViewportकोXRWebGLLayerसे वापस पाएं और इसेWebGLRenderingContextको पास करें. - फ़्रेमबफ़र में कुछ बनाएं.
पहले लेख में, पहले और दूसरे चरण के बारे में बताया गया था. इसलिए, मैं दूसरे चरण से शुरू करूँगा.
दर्शक की पोज़िशन पाना
यह बताने की ज़रूरत नहीं है. एआर या वीआर में कुछ भी बनाने के लिए, मुझे यह जानना ज़रूरी है कि दर्शक कहां है और वह कहां देख रहा है. दर्शक की पोज़िशन और ओरिएंटेशन की जानकारी, XRViewerPose ऑब्जेक्ट से मिलती है. मैंने मौजूदा ऐनिमेशन फ़्रेम पर XRFrame.getViewerPose() को कॉल करके, व्यूअर की पोज़िशन का पता लगाया. मैंने सेशन सेट अप करते समय, रेफ़रंस स्पेस को पास किया था. इस ऑब्जेक्ट से मिली वैल्यू हमेशा उस रेफ़रंस स्पेस के हिसाब से होती हैं जिसके लिए मैंने मौजूदा सेशन में शामिल होने के दौरान अनुरोध किया था. आपको याद होगा कि पोज़ का अनुरोध करते समय, मुझे मौजूदा रेफ़रंस स्पेस पास करना होता है.
function onXRFrame(hrTime, xrFrame) {
let xrSession = xrFrame.session;
xrSession.requestAnimationFrame(onXRFrame);
let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);
if (xrViewerPose) {
// Render based on the pose.
}
}
दर्शक की एक पोज़ होती है, जो उपयोगकर्ता की पूरी पोज़िशन को दिखाती है. इसका मतलब है कि दर्शक का सिर या फ़ोन का कैमरा.
पोज़ से आपके ऐप्लिकेशन को पता चलता है कि दर्शक कहां है. इमेज रेंडर करने के लिए, XRView ऑब्जेक्ट का इस्तेमाल किया जाता है. इसके बारे में हम आपको कुछ देर में बताएंगे.
आगे बढ़ने से पहले, मैं यह जांच करता हूं कि अगर सिस्टम ट्रैकिंग की सुविधा बंद कर देता है या निजता से जुड़ी वजहों से पोज़ को ब्लॉक कर देता है, तो क्या दर्शक का पोज़ वापस आ गया है. ट्रैकिंग, XR डिवाइस की ऐसी सुविधा है जिससे यह पता चलता है कि डिवाइस और उसके इनपुट डिवाइस, आस-पास के माहौल के हिसाब से कहां हैं. ट्रैकिंग कई तरीकों से बंद हो सकती है. यह ट्रैकिंग के लिए इस्तेमाल किए गए तरीके पर निर्भर करती है. उदाहरण के लिए, अगर डिवाइस को ट्रैक करने के लिए हेडसेट या फ़ोन के कैमरों का इस्तेमाल किया जाता है, तो कम या बिलकुल रोशनी न होने पर डिवाइस यह पता नहीं लगा पाएगा कि वह कहाँ है. इसके अलावा, अगर कैमरे ढके हुए हैं, तब भी ऐसा हो सकता है.
निजता की वजह से पोज़ को ब्लॉक करने का एक उदाहरण यह है कि अगर हेडसेट, अनुमति मांगने वाला प्रॉम्प्ट जैसा सुरक्षा डायलॉग दिखा रहा है, तो ब्राउज़र इस दौरान ऐप्लिकेशन को पोज़ देना बंद कर सकता है. हालांकि, मैंने XRSession.requestAnimationFrame() को पहले ही कॉल कर दिया है, ताकि अगर सिस्टम ठीक हो जाए, तो फ़्रेम लूप जारी रहे. ऐसा न होने पर, उपयोगकर्ता एजेंट सेशन खत्म कर देगा और end इवेंट हैंडलर को कॉल करेगा.
रूट से हटकर छोटा रास्ता
अगले चरण के लिए, सेशन सेट-अप के दौरान बनाए गए ऑब्जेक्ट की ज़रूरत होती है.
याद रखें कि मैंने एक कैनवस बनाया था और उसे XR के साथ काम करने वाला Web GL रेंडरिंग कॉन्टेक्स्ट बनाने का निर्देश दिया था. यह कॉन्टेक्स्ट मुझे canvas.getContext() को कॉल करके मिला था. सभी ड्राइंग, WebGL API, WebGL2 API या WebGL पर आधारित फ़्रेमवर्क, जैसे कि Three.js का इस्तेमाल करके की जाती हैं. इस कॉन्टेक्स्ट को updateRenderState() के साथ सेशन ऑब्जेक्ट में पास किया गया था. इसके अलावा, XRWebGLLayer का नया इंस्टेंस भी पास किया गया था.
let canvas = document.createElement('canvas');
// The rendering context must be based on WebGL or WebGL2
let webGLRenContext = canvas.getContext('webgl', { xrCompatible: true });
xrSession.updateRenderState({
baseLayer: new XRWebGLLayer(xrSession, webGLRenContext)
});
WebGLFramebuffer को पास ('bind') करें
XRWebGLLayer, WebGLRenderingContext के लिए एक फ़्रेमबफ़र उपलब्ध कराता है. इसका इस्तेमाल खास तौर पर WebXR के साथ किया जाता है. साथ ही, यह रेंडरिंग कॉन्टेक्स्ट के डिफ़ॉल्ट फ़्रेमबफ़र को बदलता है. WebGL की भाषा में इसे 'बाइंडिंग' कहा जाता है.
function onXRFrame(hrTime, xrFrame) {
let xrSession = xrFrame.session;
xrSession.requestAnimationFrame(onXRFrame);
let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);
if (xrViewerPose) {
let glLayer = xrSession.renderState.baseLayer;
webGLRenContext.bindFramebuffer(webGLRenContext.FRAMEBUFFER, glLayer.framebuffer);
// Iterate over the views
}
}
हर XRView ऑब्जेक्ट पर दोहराएं
पोज़ पाने और फ़्रेमबफ़र को बाइंड करने के बाद, अब व्यूपोर्ट पाने का समय है. XRViewerPose में XRView इंटरफ़ेस की एक ऐरे होती है. इनमें से हर इंटरफ़ेस, डिसप्ले या डिसप्ले के किसी हिस्से को दिखाता है. इनमें ऐसी जानकारी होती है जिसकी मदद से, डिवाइस और देखने वाले के लिए सही जगह पर कॉन्टेंट रेंडर किया जा सकता है. जैसे, व्यू का फ़ील्ड, आंखों के बीच की दूरी, और अन्य ऑप्टिकल प्रॉपर्टी.
मुझे दो आंखों के लिए ड्रॉ करना है. इसलिए, मेरे पास दो व्यू हैं. मैं इन दोनों व्यू को लूप करता हूं और हर व्यू के लिए एक अलग इमेज ड्रॉ करता हूं.
फ़ोन पर ऑगमेंटेड रिएलिटी (एआर) की सुविधा लागू करते समय, मेरे पास सिर्फ़ एक व्यू होगा, लेकिन मैं फिर भी लूप का इस्तेमाल करूंगा. हालांकि, एक व्यू को बार-बार इस्तेमाल करना फ़ायदेमंद नहीं लगता, लेकिन ऐसा करने से आपको इमर्सिव अनुभवों के स्पेक्ट्रम के लिए एक रेंडरिंग पाथ मिलता है. WebXR और अन्य इमर्सिव सिस्टम के बीच यह एक अहम अंतर है.
function onXRFrame(hrTime, xrFrame) {
let xrSession = xrFrame.session;
xrSession.requestAnimationFrame(onXRFrame);
let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);
if (xrViewerPose) {
let glLayer = xrSession.renderState.baseLayer;
webGLRenContext.bindFramebuffer(webGLRenContext.FRAMEBUFFER, glLayer.framebuffer);
for (let xrView of xrViewerPose.views) {
// Pass viewports to the context
}
}
}
XRViewport ऑब्जेक्ट को WebGLRenderingContext में पास करें
XRView ऑब्जेक्ट का मतलब है कि स्क्रीन पर क्या दिख रहा है. हालांकि, उस व्यू को बनाने के लिए मुझे ऐसे कोऑर्डिनेट और डाइमेंशन की ज़रूरत होगी जो मेरे डिवाइस के हिसाब से हों. फ़्रेमबफ़र की तरह, मैं XRWebGLLayer से इनका अनुरोध करता हूँ और इन्हें WebGLRenderingContext को पास करता हूँ.
function onXRFrame(hrTime, xrFrame) {
let xrSession = xrFrame.session;
xrSession.requestAnimationFrame(onXRFrame);
let xrViewerPose = xrFrame.getViewerPose(xrRefSpace);
if (xrViewerPose) {
let glLayer = xrSession.renderState.baseLayer;
webGLRenContext.bindFramebuffer(webGLRenContext.FRAMEBUFFER, glLayer.framebuffer);
for (let xrView of xrViewerPose.views) {
let viewport = glLayer.getViewport(xrView);
webGLRenContext.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
// Draw something to the framebuffer
}
}
}
The webGLRenContext
webGLRenContext ऑब्जेक्ट के नाम को लेकर, मेरी कुछ सहकर्मियों के साथ बहस हुई. सैंपल स्क्रिप्ट और ज़्यादातर WebXR कोड, इस वैरिएबल gl को कॉल करते हैं. नमूनों को समझने के दौरान, मैं यह भूल जाता था कि gl का क्या मतलब है. मैंने इसे webGLRenContext कहा है, ताकि आपको याद रहे कि यह WebGLRenderingContext का उदाहरण है.
इसकी वजह यह है कि gl का इस्तेमाल करने से, तरीके के नाम OpenGL ES 2.0 API में मौजूद नामों जैसे दिखते हैं. इस API का इस्तेमाल, कंपाइल की गई भाषाओं में वीआर बनाने के लिए किया जाता है. अगर आपने OpenGL का इस्तेमाल करके वीआर ऐप्लिकेशन बनाए हैं, तो आपको इस बारे में पता होगा. हालांकि, अगर आपने इस टेक्नोलॉजी का इस्तेमाल पहले कभी नहीं किया है, तो आपको यह जानकारी समझने में मुश्किल हो सकती है.
फ़्रेमबफ़र पर कुछ ड्रा करना
अगर आपको कुछ नया आज़माना है, तो WebGL का सीधे तौर पर इस्तेमाल किया जा सकता है. हालांकि, हम ऐसा करने का सुझाव नहीं देते. ऊपर दी गई सूची में शामिल किसी एक फ़्रेमवर्क का इस्तेमाल करना ज़्यादा आसान है.
नतीजा
WebXR से जुड़े अपडेट या लेख यहीं खत्म नहीं होते. MDN पर, WebXR के सभी इंटरफ़ेस और सदस्यों के बारे में जानकारी देखी जा सकती है. इंटरफ़ेस में होने वाले आने वाले समय के सुधारों के बारे में जानने के लिए, Chrome Status पर जाकर अलग-अलग सुविधाओं के बारे में पढ़ें.