हॉबिट एक्सपीरियंस

मोबाइल WebGL के साथ मध्य-पृथ्वी को जीवन में उतारना

पुराने समय से, मोबाइल और टैबलेट पर इंटरैक्टिव, वेब पर आधारित, मल्टीमीडिया से भारी अनुभव देना काफ़ी चुनौती भरा काम रहा है. परफ़ॉर्मेंस, एपीआई की उपलब्धता, डिवाइसों पर HTML5 ऑडियो में सीमाएं, और बिना किसी रुकावट के इनलाइन वीडियो प्लेबैक न होना मुख्य समस्याएं हैं.

इस साल की शुरुआत में हमने नई Hobbit फ़िल्म, The Hobbit: The Desolation of Smaug के लिए मोबाइल-फ़र्स्ट वेब अनुभव बनाने के लिए Google और Warner Bros. के दोस्तों के साथ एक प्रोजेक्ट शुरू किया था. एक मल्टीमीडिया से भरा मोबाइल Chrome प्रयोग बनाना वाकई में प्रेरणा देने वाला और चुनौती भरा काम रहा है.

अनुभव को नए Nexus डिवाइसों पर Android के लिए Chrome के लिए ऑप्टिमाइज़ किया गया है, जहां अब हमारे पास WebGL और वेब ऑडियो का ऐक्सेस है. हालांकि, हार्डवेयर-एक्सेलरेटेड कंपोज़िटिंग और सीएसएस ऐनिमेशन की वजह से, इस अनुभव का एक बड़ा हिस्सा गैर-WebGL डिवाइसों और ब्राउज़र पर भी ऐक्सेस किया जा सकता है.

यह पूरा अनुभव मिडिल अर्थ के मैप और हॉबिट की फ़िल्मों के किरदारों और जगहों पर आधारित है. WebGL का इस्तेमाल करने से हमारे लिए हॉबिट की तीन सबसे शानदार दुनिया को नाटकीय अंदाज़ में एक्सप्लोर करना और एक्सप्लोर करना मुमकिन हो गया. साथ ही, इससे लोगों को अपना अनुभव जानने का मौका मिला.

मोबाइल डिवाइसों पर WebGL के ज़रिए आने वाली चुनौतियां

पहली, "मोबाइल डिवाइस" शब्द बहुत व्यापक है. डिवाइसों के मटीरियल में कई तरह के बदलाव हो सकते हैं. इसलिए, डेवलपर के तौर पर आपको यह तय करना होगा कि आपको ज़्यादा डिवाइसों पर काम करना है या नहीं. हालांकि, जैसा कि हमने इस मामले में किया है, 3D की दुनिया को असल लगने वाले डिवाइस ही दिखाएं. “Journey through मिड- अर्थ” में हमने Nexus डिवाइसों और पांच लोकप्रिय Android स्मार्टफ़ोन पर फ़ोकस किया.

इस प्रयोग में, हमने three.js का इस्तेमाल किया, जैसा कि हमने अपने कुछ पुराने WebGL प्रोजेक्ट के लिए किया है. हमने Trollhaw गेम के एक ऐसे शुरुआती वर्शन को बनाकर उसे लागू करना शुरू किया है, जो Nexus 10 टैबलेट पर अच्छी तरह से चलेगा. डिवाइस की कुछ शुरुआती टेस्टिंग के बाद, हमारे दिमाग में ऑप्टिमाइज़ेशन की एक सूची आई थी. यह बहुत कम सुविधाओं वाले लैपटॉप की तरह दिखती है, जिसे हम आम तौर पर इस्तेमाल करते हैं:

  • लो-पॉली मॉडल का इस्तेमाल करना
  • लो रिज़ॉल्यूशन वाली बनावटों का इस्तेमाल करें
  • ज्यामिति मर्ज करके, ड्रॉकॉल की संख्या को जितना हो सके कम करें
  • सामान और रोशनी को आसान बनाएं
  • पोस्ट के इफ़ेक्ट हटाएं और एंटीएलियासिंग बंद करें
  • JavaScript की परफ़ॉर्मेंस को ऑप्टिमाइज़ करें
  • WebGL कैनवस को आधे आकार में रेंडर करना और सीएसएस के साथ बढ़ाना

इन ऑप्टिमाइज़ेशन को गेम के अपने पहले रफ़ वर्शन पर लागू करने के बाद, हमारा फ़्रेम रेट 30 FPS (फ़्रेम प्रति सेकंड) तक बना रहा और हमें इससे खुशी हुई. उस समय हमारा लक्ष्य, फ़्रेम रेट पर बुरा असर डाले बिना विज़ुअल को बेहतर बनाना था. हमने कई तरकीबें आज़माईं: कुछ तरीकों से परफ़ॉर्मेंस पर काफ़ी असर पड़ा. कुछ तरीकों ने हमारी उम्मीद के मुताबिक बदलाव नहीं किया.

लो-पॉली मॉडल का इस्तेमाल करना

आइए मॉडल से शुरुआत करते हैं. लो-पॉली मॉडल का इस्तेमाल करने से, डाउनलोड होने वाले समय के साथ-साथ सीन शुरू होने में लगने वाले समय में भी आसानी होती है. हमने पाया कि हम परफ़ॉर्मेंस पर ज़्यादा असर डाले बिना, जटिलता को काफ़ी बढ़ा सकते हैं. इस गेम में हमने ट्रोल करने वाले जिन मॉडल का इस्तेमाल किया है उनमें करीब 5,000 चेहरे हैं और सीन करीब 40 हज़ार चेहरों वाला है. इसलिए, यह बात सही है.

ट्रोलशॉ जंगल के ट्रोल्स में से एक
ट्रोलशॉ जंगल के ट्रोल में से एक

अनुभव में दूसरी (अभी रिलीज़ नहीं की गई) जगह के लिए, हमें पॉलीगॉन कम करने से परफ़ॉर्मेंस पर ज़्यादा असर दिखा. इस मामले में, हमने डेस्कटॉप के लिए लोड किए गए ऑब्जेक्ट की तुलना में, मोबाइल डिवाइसों के लिए लोअर-पॉलीगॉन ऑब्जेक्ट को लोड किया. 3D मॉडल के अलग-अलग सेट बनाने के लिए कुछ अतिरिक्त काम की आवश्यकता होती है और यह हमेशा आवश्यक नहीं होता है. वास्तव में यह इस पर निर्भर करता है कि आपके मॉडल कितने जटिल हैं.

बहुत सारी चीज़ों के साथ बड़े पर्दे पर काम करते समय, हमने ज्यामिति को बांटने के तरीके के बारे में रणनीति बनाने की कोशिश की. इससे हम कम ज़रूरी मेश को जल्दी से चालू और बंद कर पाए, ताकि एक ऐसी सेटिंग मिल सके जो सभी मोबाइल डिवाइसों के लिए काम करे. इसके बाद, हम डाइनैमिक ऑप्टिमाइज़ेशन के लिए रनटाइम के दौरान JavaScript में ज्यामिति को मर्ज कर सकते हैं या अनुरोधों को सेव करने के लिए प्री-प्रोडक्शन में मर्ज कर सकते हैं.

लो रिज़ॉल्यूशन वाली बनावटों का इस्तेमाल करें

मोबाइल डिवाइस पर लोड होने में लगने वाले समय को कम करने के लिए, हमने अलग-अलग बनावटों को लोड करने का विकल्प चुना. ये बनावट डेस्कटॉप की बनावट से आधी होती. सभी डिवाइस 2048x2048 पिक्सल तक टेक्स्चर के साइज़ को हैंडल कर सकते हैं और ज़्यादातर डिवाइस 4096x4096 पिक्सल तक की स्क्रीन हैंडल कर सकते हैं. जीपीयू पर अपलोड होने के बाद, अलग-अलग टेक्सचर पर टेक्सचर लुकअप से जुड़ी कोई समस्या नहीं है. बनावट का कुल आकार जीपीयू मेमोरी में फ़िट होना चाहिए, ताकि बनावट लगातार अप-टू-डेट न रहे और डाउनलोड भी न हो. हालांकि, ज़्यादातर वेब-अनुभवों के लिए यह शायद कोई बड़ी समस्या नहीं है. हालांकि, ड्रॉकॉल को कम करने के लिए टेक्सचर को कम से कम स्प्राइटशीट में मिलाना ज़रूरी है. इससे मोबाइल डिवाइस की परफ़ॉर्मेंस पर काफ़ी असर पड़ता है.

ट्रोलशॉ जंगल के एक ट्रोल की जगह की बनावट
ट्रॉलशॉ जंगल के ट्रोल्स का टेक्स्चर
(मूल साइज़ 512x512 पिक्सल)

सामान और रोशनी को आसान बनाएं

सामग्री के चुनाव से परफ़ॉर्मेंस पर भी बहुत ज़्यादा असर पड़ सकता है और इसे मोबाइल पर समझदारी से मैनेज किया जाना चाहिए. MeshPhongMaterial (हर टेक्सेल लाइट कैलकुलेशन) के बजाय, तीन.js में MeshLambertMaterial (हर वर्टेक्स लाइट कैलकुलेशन) का इस्तेमाल करके, हमने परफ़ॉर्मेंस को बेहतर बनाया है. दरअसल, हमने रोशनी का कम से कम हिसाब लगाने के साथ-साथ आसान शेडर इस्तेमाल करने की कोशिश की.

यह देखने के लिए कि वीडियो में इस्तेमाल किए गए मटीरियल का किसी सीन की परफ़ॉर्मेंस पर क्या असर पड़ता है, MeshBasicMaterial से सीन के कॉन्टेंट को बदला जा सकता है . इससे आपकी तुलना सही तरीके से हो जाएगी.

scene.overrideMaterial = new THREE.MeshBasicMaterial({color:0x333333, wireframe:true});

JavaScript की परफ़ॉर्मेंस को ऑप्टिमाइज़ करना

मोबाइल के लिए गेम बनाते समय, जीपीयू हमेशा सबसे बड़ी रुकावट नहीं होता. सीपीयू (CPU) पर काफ़ी समय बिताते हैं, खास तौर पर फ़िज़िक्स और कंकाल के ऐनिमेशन पर. एक ऐसी तरकीब जो कभी-कभी, सिम्युलेशन के आधार पर मदद करती है, वह है हर दूसरे फ़्रेम में सिर्फ़ इन महंगे कैलकुलेशन को करना. ऑब्जेक्ट पूल करने, कचरा इकट्ठा करने, और ऑब्जेक्ट बनाने के लिए उपलब्ध JavaScript ऑप्टिमाइज़ेशन तकनीकों का भी इस्तेमाल किया जा सकता है.

नए ऑब्जेक्ट बनाने के बजाय, पहले से तय किए गए ऑब्जेक्ट को लूप में अपडेट करना, गेम के दौरान कचरा इकट्ठा करने वाली "हिचक" से बचने का एक अहम कदम है.

उदाहरण के लिए, इस तरह के कोड पर विचार करें:

var currentPos = new THREE.Vector3();

function gameLoop() {
  currentPos = new THREE.Vector3(0+offsetX,100,0);
}

इस लूप का बेहतर वर्शन ऐसे नए ऑब्जेक्ट बनाने से बचता है जिन्हें कचरा इकट्ठा किया जाना चाहिए:

var originPos = new THREE.Vector3(0,100,0);
var currentPos = new THREE.Vector3();
function gameLoop() {
  currentPos.copy(originPos).x += offsetX;
  //or
  currentPos.set(originPos.x+offsetX,originPos.y,originPos.z);
}

जितना हो सके, इवेंट हैंडलर को सिर्फ़ प्रॉपर्टी अपडेट करनी चाहिए और requestAnimationFrame रेंडर-लूप हैंडल को स्टेज अपडेट करने देना चाहिए.

दूसरी सलाह है, रे-कास्टिंग के काम को ऑप्टिमाइज़ और/या प्री-कैलकुलेशन करना. उदाहरण के लिए, अगर स्टैटिक पाथ मूवमेंट के दौरान आपको मेश पर कोई ऑब्जेक्ट जोड़ना हो, तो एक लूप के दौरान पोज़िशन को "रिकॉर्ड" करें. इसके बाद, मेश पर रे-कास्ट करने के बजाय, इस डेटा से पढ़ लें. जैसा कि हम Rivendell एक्सपीरियंस में करते हैं, एक आसान लो-पॉली इनविज़िबल मेश के साथ माउस इंटरैक्शन को देखने के लिए रे-कास्ट करें. हाई-पॉली मेश पर टकरावों की खोज काफ़ी धीमी होती है और सामान्य तौर पर गेम-लूप में इससे बचना चाहिए.

WebGL कैनवस को आधे आकार में रेंडर करना और सीएसएस के साथ बढ़ाना

WebGL कैनवस का साइज़ शायद सबसे असरदार पैरामीटर है, जिसे परफ़ॉर्मेंस को बेहतर बनाने के लिए ट्वीक किया जा सकता है. कैनवस का इस्तेमाल करके 3D सीन जितना बड़ा बनाया जाएगा, हर फ़्रेम पर उतने ही ज़्यादा पिक्सल बनाने होंगे. इससे परफ़ॉर्मेंस पर असर पड़ता है.ज़्यादा डेंसिटी वाले 2560x1600 पिक्सल डिसप्ले वाले Nexus 10 को कम डेंसिटी वाले टैबलेट के रूप में पिक्सल की संख्या को चार गुना ज़्यादा बढ़ाना पड़ता है. इसे मोबाइल के लिए ऑप्टिमाइज़ करने के लिए, हम एक ट्रिक का इस्तेमाल करते हैं, जिसमें हम कैनवस को आधा साइज़ (50%) पर सेट करते हैं और फिर हार्डवेयर-Accelerated CSS 3D ट्रांसफ़ॉर्म के साथ इसे उसके सही साइज़ (100%) तक स्केल करते हैं. पिक्सलेट वाली इस इमेज में एक समस्या यह है कि इसमें पतली लाइनें समस्या हो सकती हैं, लेकिन हाई रिज़ॉल्यूशन वाली स्क्रीन पर इनका असर इतना खराब नहीं होता. यह अतिरिक्त प्रदर्शन करना पूरी तरह से फ़ायदेमंद है.

उसी सीन को Nexus 10 (16FPS) पर कैनवस स्केलिंग के बिना 50% (33FPS) पर बढ़ाया गया
Nexus 10 (16FPS) पर कैनवस स्केलिंग के बिना और 50% (33 फ़्रेम प्रति सेकंड) पर समान सीन.

बिल्डिंग ब्लॉक के रूप में ऑब्जेक्ट

Dol Guldur किले और Rivendell की कभी न खत्म होने वाली घाटी की बड़ी भूलभुलैया बनाने के लिए हमने बिल्डिंग ब्लॉक 3D मॉडल का एक सेट बनाया है, जिसे हम फिर से इस्तेमाल करते हैं. ऑब्जेक्ट का दोबारा इस्तेमाल करने से, हम यह पक्का कर पाते हैं कि उन्हें अनुभव की शुरुआत में ही इंस्टैंशिएट और अपलोड किया जाए, न कि इसके बीच में.

Dol Gulder की भूलभुलैया में उपयोग किए जाने वाले 3D ऑब्जेक्ट बिल्डिंग ब्लॉक.
Dol Guldur की भूलभुलैया में इस्तेमाल किए जाने वाले 3D ऑब्जेक्ट बिल्डिंग ब्लॉक.

Rivendell में हमारे पास ऐसे कई ग्राउंड सेक्शन हैं जिन्हें हम लगातार Z के तौर पर बदलते रहते हैं. जैसे-जैसे उपयोगकर्ता का सफ़र आगे बढ़ता है. जैसे-जैसे उपयोगकर्ता सेक्शन पास करता है, वैसे-वैसे उन्हें दूर की दूरी पर बदल दिया जाता है.

डोल गुल्दुर महल के लिए, हम चाहते थे कि हर गेम के लिए भूलभुलैया फिर से पैदा हो जाए. ऐसा करने के लिए, हमने एक स्क्रिप्ट बनाई है जो भूलभुलैया को फिर से जनरेट करती है.

शुरू से ही पूरे स्ट्रक्चर को एक बड़े मेश में मर्ज करने से बहुत बड़ा सीन मिलता है और परफ़ॉर्मेंस खराब होती है. इसे ठीक करने के लिए, हमने बिल्डिंग ब्लॉक छिपाने और दिखाने का फ़ैसला किया. यह इस बात पर निर्भर करता है कि वे मैप पर दिख रहे हैं या नहीं. शुरुआत से ही, हमें 2D रेकास्टर स्क्रिप्ट का इस्तेमाल करने का आइडिया आया था, लेकिन अंत में हमने बिल्ट-इन3.js फ़्रट्रम कलिंग का इस्तेमाल किया. हमने प्लेयर के सामने आ रहे "खतरे" पर ज़ूम इन करने के लिए रेकास्टर स्क्रिप्ट का फिर से उपयोग किया है.

दूसरी बड़ी चीज़, उपयोगकर्ता इंटरैक्शन है. डेस्कटॉप पर, माउस और कीबोर्ड इनपुट होते हैं. मोबाइल डिवाइसों पर आपके उपयोगकर्ता, टच, स्वाइप, पिंच, डिवाइस ओरिएंटेशन वगैरह से इंटरैक्ट करते हैं.

मोबाइल वेब अनुभवों में टच इंटरैक्शन का इस्तेमाल करना

टच करने की सुविधा जोड़ना मुश्किल नहीं है. यहां दिए गए विषय के बारे में पढ़ने के लिए अच्छे लेख हैं. हालांकि, कुछ छोटी चीज़ों की वजह से यह काम और भी मुश्किल हो सकता है.

आपके पास टच और माउस दोनों हो सकते हैं. Chromebook Pixel और टचस्क्रीन की सुविधा वाले अन्य लैपटॉप में माउस और टच, दोनों की सुविधा मौजूद है. एक आम गलती यह देख लेना है कि डिवाइस को टच करने की सुविधा चालू है या नहीं. इसके बाद, सिर्फ़ टच इवेंट लिसनर को जोड़ें, न कि माउस के लिए.

इवेंट लिसनर में रेंडरिंग को अपडेट न करें. इसके बजाय, टच इवेंट को वैरिएबल में सेव करें. साथ ही, requestAnimationFrame रेंडर लूप में उन पर प्रतिक्रिया दें. इससे परफ़ॉर्मेंस बेहतर होती है और कॉन्फ़्लिक्टिंग इवेंट को भी जोड़ा जा सकता है. पक्का करें कि इवेंट लिसनर में नए ऑब्जेक्ट बनाने के बजाय, ऑब्जेक्ट का फिर से इस्तेमाल किया जा रहा हो.

याद रखें कि यह मल्टीटच है: event.टच में हर तरह के टच का कलेक्शन है. कुछ मामलों में, event.targetTouches या event.changedTouches को देखना ज़्यादा दिलचस्प है और सिर्फ़ अपनी पसंद के मुताबिक प्रतिक्रिया देना चाहिए. टैप को स्वाइप से अलग करने के लिए, हम थोड़ी देर (टैप करें) से पहले यह देखते हैं कि टच मूव हुआ है (स्वाइप) हुआ है या नहीं. पिंच करने के लिए हम दो शुरुआती टच के बीच की दूरी और समय के साथ इसमें बदलाव को मापते हैं.

3D दुनिया में आपको यह तय करना होगा कि आपका कैमरा माउस बनाम स्वाइप कार्रवाइयों के लिए कैसी प्रतिक्रिया देता है. कैमरे की गतिविधि जोड़ने का एक आम तरीका यह है कि माउस की गतिविधि का पालन किया जाए. ऐसा माउस की स्थिति का इस्तेमाल करके या डेल्टा मूवमेंट (स्थिति में बदलाव) का इस्तेमाल करके, सीधे तौर पर कंट्रोल करके किया जा सकता है. आप हमेशा मोबाइल डिवाइस पर ऐसा व्यवहार नहीं चाहते जैसा डेस्कटॉप ब्राउज़र पर करता है. हमने बहुत गहराई से जांच की और यह तय किया कि हर वर्शन के लिए क्या सही है.

छोटी स्क्रीन और टचस्क्रीन वाले डिवाइसों पर, यूज़र इंटरफ़ेस (यूआई) और यूज़र इंटरफ़ेस (यूआई) इंटरैक्शन के ग्राफ़िक का अक्सर इस्तेमाल होता है. यह कुछ ऐसा है जिसे हम खास ऐप्लिकेशन डिज़ाइन करते समय करते थे, लेकिन हमें वेब अनुभवों के बारे में पहले कभी सोचने की ज़रूरत नहीं पड़ी. यह डिज़ाइनर और UX डिज़ाइनर के लिए एक बड़ी चुनौती है.

खास जानकारी

इस प्रोजेक्ट से हमारा अनुभव यह है कि मोबाइल पर WebGL अच्छी तरह से काम करता है, खास तौर से नए और महंगे डिवाइसों पर. जब परफ़ॉर्मेंस की बात आती है, तो ऐसा लगता है कि पॉलीगॉन काउंट और टेक्स्चर का साइज़, ज़्यादातर डाउनलोड और शुरू करने में लगने वाले समय पर असर डालता है. साथ ही, मोबाइल की परफ़ॉर्मेंस को ऑप्टिमाइज़ करने के लिए मटीरियल, शेडर, और WebGL कैनवस का साइज़ सबसे अहम हिस्सा है. हालांकि, यह उन हिस्सों का योग है जो परफ़ॉर्मेंस पर असर डालते हैं, इसलिए संख्या को ऑप्टिमाइज़ करने के लिए आप सभी कुछ कर सकते हैं.

मोबाइल डिवाइसों को टारगेट करने का मतलब यह भी है कि आपको अक्सर टच इंटरैक्शन के बारे में सोचना पड़ता है. साथ ही, आपको सिर्फ़ पिक्सल के साइज़ के बारे में नहीं सोचना पड़ता, बल्कि स्क्रीन का साइज़ भी देखना पड़ता है. कुछ मामलों में हमें 3D कैमरे को पास लेकर जाना पड़ता था, ताकि यह देखा जा सके कि क्या हो रहा है.

एक्सपेरिमेंट लॉन्च किया गया और यह एक शानदार सफ़र रहा. उम्मीद है कि आपको यह पसंद आएगा!

क्या आप इसे आज़माना है? मध्य-पृथ्वी का सफ़र खुद करें.