Merender Teks di WebVR

Dalam Detail

Lihat situs

Dalam (https://with.in/) adalah platform untuk bercerita dalam virtual reality. Jadi, saat tim mendengar tentang WebVR pada 2015, kami langsung tertarik dengan potensinya. Saat ini, minat tersebut terlihat pada subdomain unik platform Web kami, https://vr.with.in/. Siapa pun yang memiliki browser berkemampuan VR dapat membuka situsnya, mengklik tombol, dan menggunakan headset untuk menikmati portofolio film VR kami.

Saat ini, hal tersebut mencakup, tetapi tidak terbatas pada, Chrome di Daydream View. Untuk mengetahui informasi tentang perangkat dan layar yang dipasang di kepala, lihat https://webvr.info/.

Seperti lingkungan rendering khusus virtual reality lainnya, web sebagian besar bergantung pada representasi tiga dimensi dari suatu scene. Adegan ini memiliki kamera, perspektif Anda, dan banyak objek. Untuk membantu mengelola adegan, kamera, dan objek ini, kami menggunakan library bernama Three.js yang memanfaatkan elemen <canvas> untuk menampilkan rendering ke GPU komputer Anda. Ada banyak add-on Three.js yang berguna untuk membuat adegan terlihat di WebVR. Dua yang utama adalah THREE.VREffect untuk membuat area pandang bagi setiap mata dan THREE.VRControls untuk menerjemahkan perspektif (misalnya rotasi dan posisi layar yang dipasang di kepala) secara meyakinkan ke dalam adegan. Ada banyak contoh cara menerapkannya. Lihat contoh WebVR Three.js untuk mengetahui cara memulai.

Saat kita melangkah lebih jauh dalam eksplorasi WebVR, kita menghadapi sebuah masalah. Ketika kita melihat konten web, teks merupakan bagian integral. Meskipun sebagian besar konten kami berbasis video, jika Anda membuka Di dalam situs, teks akan mengelilingi konten; antarmuka pengguna dan informasi tambahan tentang film atau film terkait akan dibuat dengan teks. Selain itu, semua teks ini dibuat di DOM. Eksplorasi WebVR dan https://vr.with.in/ kami semuanya ada di <canvas>.

Teks yang digunakan di WebVR Teks yang digunakan di WebVR
Teks yang digunakan di WebVR untuk vr.with.in

Apa saja Opsi saya?

Untungnya, ada upaya yang sedang dilakukan untuk mewujudkan hal ini. Bahkan dalam riset, kami menemukan sejumlah cara efektif untuk merender teks dalam lingkungan tiga dimensi pada elemen <canvas>. Di bawah ini adalah matriks dari beberapa yang kami temukan yang ditandai dengan pro dan kontra untuk masing-masingnya:

Resolusi Independen Fitur Tipografi Performa Kemudahan Penerapan
Teks kanvas 2D Ya Ya Ya
Teks vektor triangulasi Ya Ya
Teks 3D yang diekstrusi Ya
Teks bitmap kolom jarak yang ditandatangani Ya Ya Ya

Keputusan Kami: Font Bitmap SDF

Kanvas 2D dengan ctx.fillText() dapat menggabungkan teks, spasi huruf, dan tinggi baris, tetapi tambahan akan terpotong, dan teks akan menjadi buram jika Anda memperbesarnya terlalu jauh. Anda dapat meningkatkan ukuran tekstur kanvas, tetapi mungkin mencapai batas atas ukuran tekstur atau performa dapat terpengaruh jika tekstur terlalu besar.

Teks 3D yang diekstrusi pada dasarnya sama dengan teks vektor triangulasi, tetapi dengan kedalaman dan mungkin bevel sehingga memiliki geometri setidaknya dua kali lebih banyak. Keduanya dapat berfungsi dalam dosis kecil untuk judul atau logo, tetapi tidak akan berperforma baik untuk teks dalam jumlah besar dan juga tidak memiliki fitur tipografi.

Font ke alur kerja bitmap SDF
Alur kerja font ke bitmap SDF

Font bitmap menggunakan satu segi empat (dua segitiga) per karakter, sehingga menggunakan lebih sedikit geometri dan berperforma lebih baik daripada vektor triangulasi. Gambar tersebut masih berbasis raster karena menggunakan sprite peta tekstur, tetapi dengan shader SDF, keduanya pada dasarnya tidak bergantung pada resolusi sehingga terlihat lebih bagus daripada tekstur kanvas 2D. teks tiga-bmfont-Matt DesLauriers juga menyertakan fitur tipografi yang andal untuk pengemasan teks, spasi huruf, tinggi baris, dan perataan. Luapan tidak terpotong. Ukuran font dikontrol melalui skala. Kami memilih rute ini karena memberi kami opsi terbaik untuk desain sekaligus tetap berperforma tinggi. Sayangnya, penerapannya tidak mudah, jadi kami akan menjelaskan langkah-langkahnya dengan harapan dapat membantu sesama developer yang bekerja di WebVR.

1. Membuat font bitmap (.png + .fnt)

Antarmuka Hiero
Antarmuka Hiero
Output Hiero (file PNG dan .fnt Bitmap) Output Hiero (file PNG dan .fnt Bitmap)
Output Hiero (file PNG dan .fnt Bitmap)

Hiero adalah alat pengemasan font bitmap yang berjalan dengan Java. Dokumentasi Hiero tidak benar-benar menjelaskan cara menjalankannya tanpa melalui proses build yang rumit. Pertama, instal Java jika Anda belum melakukannya. Kemudian, jika klik dua kali pada runnable-hiero.jar tidak membuka Hiero, coba jalankan dengan perintah ini di konsol:

java -jar runnable-hiero.jar

Setelah Hiero berjalan, buka font desktop .ttf atau .otf, masukkan karakter tambahan yang ingin Anda sertakan, ubah rendering ke Java untuk mengaktifkan efek, memperbesar ukurannya sehingga karakter Anda mengisi seluruh kotak cache glyph, menambahkan efek kolom jarak, menyesuaikan skala dan penyebaran kolom jarak. Nilai skala seperti resolusi. Semakin tinggi nilainya, semakin kecil efek buramnya, tetapi semakin lama waktu yang dibutuhkan Hiero untuk merender pratinjau. Kemudian, simpan font bitmap Anda. Library ini menghasilkan font bitmap yang terdiri dari gambar .png dan file deskripsi font .fnt AngelCode.

2. Mengonversi AngelCode ke JSON

Setelah font bitmap dibuat, kita harus memuatnya ke dalam aplikasi JavaScript dengan paket npm load-bmfont Matt DesLauriers.

Kita dapat melakukan browserify load-bmfont dan menggunakannya di front end, tetapi kita akan menjalankan load-bmfont.js dengan Node untuk mengonversi dan menyimpan AngelCode .fnt Hiero ke file.json:

npm install
node load-bmfont.js
Contoh JSON output
Contoh JSON output

Sekarang kita dapat mengabaikan load-bmfont dan cukup melakukan permintaan XHR (XMLHttpRequest) pada file font .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 teks tiga-bmfont

Setelah font dimuat, tiga-bmfont-text Matt akan menangani sisanya. Karena kita tidak menggunakan Node untuk aplikasi sendiri, kita akan browserify three-bmfont-text.js menjadi three-bmfont-text-bundle.js yang dapat digunakan

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

4. Shader SDF

Sesuaikan penggeser afwidth dan threshold di vr.with.in/archive/text-sdf-bitmap/ untuk melihat pengaruh shader kolom jarak yang ditandatangani.

5. Penggunaan

Demi kemudahan, saya membuat class wrapper TextBitmap untuk tiga-bmfont-text yang di-browser.

Cara kerja text-sdf-bitmap
Penerapan text-sdf-bitmap
<script src="three-bmfont-text-bundle.js"></script>
<script src="sdf-shader.js"></script>
<script src="text-bitmap.js"></script>

Buat permintaan XHR untuk file font .json dan buat objek teks di callback:

var bmtext = new TextBitmap({ options });

Untuk mengubah teks:

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

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

.png font bitmap dimuat dengan THREE.TextureLoader di text-bitmap.js

TextBitmap juga menyertakan hitbox tak terlihat untuk interaksi raycast tiga.js melalui mouse, kamera, atau pengontrol gerakan yang dilacak dengan tangan seperti Oculus Touch atau pengontrol Vive. Ukuran hitbox akan otomatis diperbarui saat Anda mengubah opsi teks.

Bmtext.group ditambahkan ke tampilan tiga.js. Jika Anda perlu mengakses turunan/Object3D, grafik scene untuk teks akan terlihat seperti ini:

Diagram sistem file

6. Perkecil json dan ubah xoffset

Gif dalam teks

Jika kerning Anda terlihat tidak aktif, Anda mungkin perlu mengedit xoffset dalam json. Tempelkan json ke Jsbeautifier.org untuk mendapatkan versi file yang tidak diminifikasi.

Xoffset pada dasarnya adalah kerning global untuk satu karakter. Kerning ditujukan untuk dua karakter tertentu yang muncul berdampingan satu sama lain. Nilai default dalam array kernel tidak benar-benar berpengaruh, dan akan terlalu membosankan untuk diedit, jadi Anda dapat mengosongkan array tersebut untuk mengurangi ukuran file JSON. Kemudian, edit xoffset untuk kerning.

Pertama, Anda harus mencari tahu karakter apa yang cocok dengan ID karakter dalam json. Di three-bmfont-text-bundle.js, sisipkan console.log setelah baris 240:

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

Kemudian, ketik kolom teks dat.gui di https://vr.with.in/archive/text-sdf-bitmap/ dan periksa konsol untuk menemukan ID karakter yang sesuai.

Misalnya, dalam font bitmap, "j" secara konsisten terlalu jauh ke kanan. ID karakternya adalah 106. Jadi, temukan "id": 106 dalam json dan ubah xoffsetnya dari -1 menjadi -10.

7. Tata Letak

Jika Anda memiliki beberapa blok teks dan ingin teks mengalir dari atas ke bawah seperti HTML, semuanya harus diposisikan secara manual, mirip dengan penempatan absolut setiap elemen dom dengan CSS. Dapatkah Anda membayangkan melakukannya di CSS?

    * { position: absolute; }

Seperti itulah tata letak teks dalam 3D. Pada tampilan detail: judul, penulis, deskripsi, dan durasi masing-masing merupakan objek TextBitmap baru dengan gaya, warna, skalanya sendiri, dll.:

Tata letak 3d
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;

Hal ini mengasumsikan bahwa asal lokal setiap grup TextBitmap disejajarkan secara vertikal dengan bagian atas mesh TextBitmap (lihat pemusatan di update text-bitmap.js). Jika nantinya Anda mengubah teks untuk salah satu objek tersebut, dan tinggi objek tersebut berubah, Anda juga harus menghitung ulang posisi tersebut. Di sini, hanya posisi y pada teks yang dimodifikasi, tetapi satu peluang untuk bekerja dalam 3D adalah kita dapat mendorong dan menarik teks ke arah z, serta memutar sumbu x, y dan z.

Kesimpulan

Teks dan tata letak di WebVR memiliki banyak cara sebelum menjadi semudah dan digunakan secara luas seperti HTML dan CSS. Tetapi ada solusi yang bekerja dan Anda dapat melakukan lebih banyak di WebVR daripada di laman web HTML tradisional. WebVR ada saat ini. Mungkin akan ada alat yang lebih baik besok. Sementara itu, cobalah dan lakukan eksperimen. Mengembangkan aplikasi tanpa framework yang ada di mana-mana akan menghasilkan project yang lebih unik, dan hal ini sangat menarik.