رندر کردن متن در WebVR

در جزئیات

سایت را مشاهده کنید

درون ( https://with.in/ ) بستری برای داستان سرایی در واقعیت مجازی است. بنابراین وقتی تیم در سال 2015 درباره WebVR شنید، بلافاصله به پتانسیل آن علاقه مند شدیم. امروزه، این علاقه در یک زیر دامنه منحصر به فرد از پلتفرم وب ما، https://vr.with.in/ آشکار می شود. هر کسی که یک مرورگر مجهز به واقعیت مجازی دارد می‌تواند به سایت برود، روی یک دکمه کلیک کند و هدستی را روی آن بیاندازد تا در مجموعه فیلم‌های واقعیت مجازی ما غوطه‌ور شود.

امروز که شامل Chrome on Daydream View می شود، اما محدود به آن نیست. برای اطلاعات در مورد دستگاه خود و صفحه نمایش روی سر ، https://webvr.info/ را بررسی کنید.

مانند سایر محیط‌های رندر ویژه واقعیت مجازی، وب عمدتاً بر نمایش سه بعدی یک صحنه متکی است. این صحنه دارای دوربین، پرسپکتیو شما و هر تعداد شی است. برای کمک به مدیریت این صحنه، دوربین و اشیا، از کتابخانه‌ای به نام Three.js استفاده می‌کنیم که از عنصر <canvas> برای پرتاب کردن رندر روی GPU رایانه شما استفاده می‌کند. بسیاری از افزونه های مفید Three.js برای قابل مشاهده کردن صحنه شما در WebVR وجود دارد. دو مورد اصلی عبارتند از THREE.VREffect برای ایجاد یک دریچه دید برای هر چشم و THREE.VRCکنترل برای ترجمه قانع کننده پرسپکتیو (مثلاً چرخش و موقعیت نمایشگر نصب شده روی سر) به صحنه شما. مثال های زیادی از نحوه اجرای این کار وجود دارد. برای راه‌های شروع ، نمونه‌های Three.js WebVR را بررسی کنید.

همانطور که به کاوش WebVR خود ادامه دادیم، با مشکلی مواجه شدیم. اگر به محتویات وب نگاه کنیم، متن جزء لاینفک آن است. در حالی که اکثر محتوای ما مبتنی بر ویدیو است، اگر به داخل سایت بروید، متن اطراف محتوا را احاطه کرده است. رابط کاربری و اطلاعات اضافی درباره یک فیلم یا فیلم‌های مرتبط همگی با متن ساخته می‌شوند. علاوه بر این، تمام این متن در DOM ایجاد می شود. کاوش های WebVR ما و https://vr.with.in/ همه در <canvas> هستند.

متن استفاده شده در WebVRمتن استفاده شده در WebVR
متن استفاده شده در WebVR برای vr.with.in

گزینه های من چیست؟

خوشبختانه کارهایی در حال انجام است تا این امکان فراهم شود. در واقع در تحقیقات خود ما تعدادی روش موثر برای ارائه متن در یک محیط سه بعدی بر روی یک عنصر <canvas> پیدا کردیم. در زیر ماتریسی از چند موردی است که با مزایا و معایب برای هر کدام مشخص شده‌اند:

رزولوشن مستقل ویژگی های تایپوگرافی عملکرد سهولت اجرا
متن بوم دوبعدی بله بله بله
متن وکتور مثلثی بله بله
متن سه بعدی اکسترود شده بله
متن نقشه بیت فیلد فاصله امضا شده بله بله بله

تصمیم ما: قلم بیت مپ SDF

بوم دوبعدی با ctx.fillText() می تواند بسته بندی متن، فاصله حروف و ارتفاع خط را انجام دهد، اما سرریز قطع می شود و اگر خیلی زیاد زوم کنید، متن تار می شود. شما می توانید اندازه بافت بوم را افزایش دهید، اما ممکن است به حد بالایی در اندازه بافت برسد یا اگر بافت بیش از حد بزرگ باشد، عملکرد آن ممکن است آسیب ببیند.

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

گردش کار بیت مپ فونت به SDF
گردش کار بیت مپ فونت به SDF

فونت های بیت مپ از یک چهارگوش (دو مثلث) در هر کاراکتر استفاده می کنند، بنابراین از هندسه کمتری استفاده می کنند و عملکرد بهتری نسبت به بردارهای مثلثی دارند. آنها هنوز هم مبتنی بر شطرنجی هستند زیرا از یک بافت نقشه بافت استفاده می کنند، اما با سایه زن SDF اساساً مستقل از وضوح هستند بنابراین از بافت بوم دو بعدی زیباتر به نظر می رسند. متن سه bmfont Matt DesLauriers همچنین شامل ویژگی‌های تایپوگرافی قابل اعتماد برای بسته بندی متن، فاصله حروف، ارتفاع خط و تراز است. سرریز قطع نمی شود. اندازه قلم از طریق مقیاس کنترل می شود. ما این مسیر را انتخاب کردیم زیرا بهترین گزینه‌ها را برای طراحی و در عین حال کارآمد به ما می‌داد. متأسفانه، پیاده سازی آن به این آسانی نبود، بنابراین به امید کمک به توسعه دهندگان همکار در WebVR، مراحل را طی خواهیم کرد.

1. یک فونت بیت مپ (png. + fnt.) ایجاد کنید

رابط Hiero
رابط Hiero
خروجی Hiero (Bitmap PNG و فایل fnt.)خروجی Hiero (Bitmap PNG و فایل fnt.)
خروجی Hiero (Bitmap PNG و فایل fnt.)

Hiero یک ابزار بسته بندی فونت بیت مپ است که با جاوا اجرا می شود. مستندات Hiero در واقع نحوه اجرای آن را بدون گذراندن فرآیند ساخت پیچیده توضیح نمی دهد. ابتدا اگر جاوا را نصب نکرده اید. سپس، اگر روی runnable-hiero.jar دوبار کلیک کنید Hiero را باز نکرد، سعی کنید آن را با این دستور در کنسول اجرا کنید:

java -jar runnable-hiero.jar

هنگامی که Hiero در حال اجرا است، یک فونت دسکتاپ .ttf یا .otf را باز کنید، هر کاراکتر اضافی را که می‌خواهید وارد کنید، رندر را به جاوا تغییر دهید تا افکت‌ها فعال شوند، اندازه را افزایش دهید تا کاراکترهای شما کل مربع حافظه پنهان گلیف را پر کنند، یک فیلد فاصله اضافه کنید. اثر، مقیاس و گسترش میدان فاصله را تنظیم کنید. مقدار مقیاس مانند یک وضوح است. هرچه بالاتر باشد، تاری کمتری خواهد داشت، اما زمان بیشتری طول می کشد تا Hiero پیش نمایش را ارائه دهد. سپس فونت بیت مپ خود را ذخیره کنید. این یک فونت بیت مپ متشکل از یک تصویر png. و یک فایل توضیحات فونت AngelCode .fnt تولید می کند.

2. AngelCode را به JSON تبدیل کنید

اکنون که فونت بیت مپ تولید شده است، باید آن را با بسته load-bmfont npm Matt DesLauriers در برنامه جاوا اسکریپت بارگذاری کنیم.

ما می‌توانیم load-bmfont را مرورگر کنیم و از آن در قسمت جلویی استفاده کنیم، اما در عوض، load-bmfont.js را با Node اجرا می‌کنیم تا AngelCode.fnt Hiero را به یک فایل json. تبدیل و ذخیره کنیم:

npm install
node load-bmfont.js
نمونه ای از خروجی JSON
نمونه ای از خروجی JSON

اکنون می توانیم load-bmfont را دور بزنیم و فقط یک درخواست XHR (XMLHttpRequest) روی فایل فونت .json انجام دهیم.

var r = new XMLHttpRequest();
r.open('GET', 'fonts/roboto/bitmap/roboto-bold.json');

r.onreadystatechange = function() {
    if (r.readyState === 4 && r.status === 200) {
    setup(JSON.parse(r.responseText));
    }
};

r.send();

function setup(font) {
    // pass font into TextBitmap object
}

3. Browserify three-bmfont-text

هنگامی که فونت را بارگذاری کردیم، متن سه bmfont مت از بقیه مراقبت خواهد کرد. از آنجایی که ما از Node برای برنامه خود استفاده نمی کنیم، می خواهیم three-bmfont-text.js را به یک سه bmfont-text-bundle.js قابل استفاده مرور کنیم .

npm install -g browserify
browserify three-bmfont-text.js -o three-bmfont-text-bundle.js

4. شیدر SDF

لغزنده های afwidth و آستانه را در vr.with.in/archive/text-sdf-bitmap/ تنظیم کنید تا تأثیر سایه زن فیلد فاصله امضا شده را ببینید.

5. استفاده

برای راحتی، یک کلاس بسته بندی TextBitmap برای متن سه bmfont مرورگر ایجاد کردم.

متن-sdf-bitmap در عمل
متن-sdf-bitmap در عمل
<script src="three-bmfont-text-bundle.js"></script>
<script src="sdf-shader.js"></script>
<script src="text-bitmap.js"></script>

یک درخواست XHR برای فایل فونت .json ایجاد کنید و یک آبجکت متنی در callback ایجاد کنید:

var bmtext = new TextBitmap({ options });

برای تغییر متن:

bmtext.text = 'The quick brown fox jumps over the lazy dog.';

scene.add( bmtext.group );
hitBoxes.push( bmtext.hitBox );

png. فونت بیت مپ با THREE.TextureLoader در text-bitmap.js بارگیری می شود.

TextBitmap همچنین شامل یک هیت باکس نامرئی برای تعامل پرتوهای three.js از طریق ماوس، دوربین یا کنترل‌کننده‌های حرکتی ردیابی دستی مانند Oculus Touch یا کنترل‌کننده‌های Vive است. وقتی گزینه‌های نوشتاری را تغییر می‌دهید، اندازه hitbox به‌طور خودکار به‌روزرسانی می‌شود.

Bmtext.group به صحنه three.js اضافه می شود. اگر نیاز به دسترسی به کودکان / Object3D دارید، نمودار صحنه برای متن به نظر می رسد:

نمودار سیستم فایل

6. json را Unminify کنید و xoffsets را تغییر دهید

درون متن گیف

اگر kerning شما به نظر خارج است، ممکن است لازم باشد xoffsets را در json ویرایش کنید. json را در Jsbeautifier.org بچسبانید تا یک نسخه کوچک نشده از فایل دریافت کنید.

xoffset اساساً یک هسته جهانی برای یک کاراکتر است. Kerning برای دو شخصیت خاص است که در کنار یکدیگر ظاهر می شوند. مقادیر پیش‌فرض در آرایه هسته عملاً تفاوتی ایجاد نمی‌کنند، و ویرایش آن خیلی خسته‌کننده است، بنابراین می‌توانید آن آرایه را خالی کنید تا اندازه فایل json را کاهش دهید. سپس xoffset ها را برای کرنینگ ویرایش کنید.

ابتدا باید بفهمید که کدام کاراکترها با کدام ID char در json مطابقت دارند. در three-bmfont-text-bundle.js ، console.log بعد از خط 240 وارد کنید:

    var id = text.charCodeAt(i)
    // console.log(id);

سپس در قسمت متنی dat.gui در https://vr.with.in/archive/text-sdf-bitmap/ تایپ کنید و کنسول را بررسی کنید تا شناسه مربوط به یک کاراکتر را بیابید.

به عنوان مثال، در فونت بیت مپ ما، "j" به طور مداوم بیش از حد به سمت راست است. شناسه کاراکتر آن 106 است. بنابراین "id": 106 در json پیدا کنید و xoffset آن را از -1 به -10 تغییر دهید.

7. چیدمان

اگر چندین بلوک متن دارید و می‌خواهید مانند HTML از بالا به پایین جریان داشته باشد، همه چیز باید به صورت دستی قرار گیرد، شبیه به موقعیت مطلق هر عنصر dom با CSS. آیا می توانید تصور کنید که این کار را در CSS انجام دهید؟

    * { position: absolute; }

چیدمان متن در سه بعدی اینگونه است. در نمای جزئیات: عنوان، نویسنده، توضیحات و مدت زمان هر کدام یک شی TextBitmap جدید با سبک، رنگ، مقیاس و غیره خاص خود هستند:

چیدمان سه بعدی
author.group.position.y = title.group.position.y - title.height - padding;
description.group.position.y = author.group.position.y - author.height - padding;
duration.group.position.y = description.group.position.y - description.height - padding;

این فرض را بر این می‌گذارد که مبدا محلی هر گروه TextBitmap به صورت عمودی با بالای مش TextBitmap تراز است (به مرکز در به‌روزرسانی text-bitmap.js مراجعه کنید). اگر بعداً متن هر یک از آن اشیاء را تغییر دهید و ارتفاع آن شیء تغییر کند، باید آن موقعیت ها را مجدداً محاسبه کنید. در اینجا فقط موقعیت y متن تغییر می کند، اما یکی از فرصت های کار در سه بعدی این است که می توانیم متن را در جهت z فشار داده و بکشیم و همچنین حول محورهای x، y و z بچرخانیم.

نتیجه گیری

متن و طرح‌بندی در WebVR راه درازی در پیش دارند تا اینکه به آسانی و به اندازه HTML و CSS مورد استفاده قرار گیرند. اما راه‌حل‌های کاری وجود دارد و شما می‌توانید در WebVR خیلی بیشتر از یک صفحه وب سنتی HTML انجام دهید. WebVR امروزه وجود دارد. احتمالا فردا ابزارهای بهتری وجود خواهد داشت. تا آن زمان، آن را امتحان کنید و آزمایش کنید. توسعه بدون چارچوبی فراگیر منجر به پروژه های منحصر به فرد بیشتری می شود و این هیجان انگیز است.