การแสดงผลข้อความใน WebVR

ภายในรายละเอียด

ดูเว็บไซต์

ภายใน (https://with.in/) เป็นแพลตฟอร์มสำหรับการเล่าเรื่องในแบบ Virtual Reality ดังนั้นเมื่อทีมได้ยินเกี่ยวกับ WebVR ในปี 2015 เราจึงสนใจในศักยภาพของระบบนี้ทันที ปัจจุบันความสนใจดังกล่าวแปรเปลี่ยนไปเป็นโดเมนย่อยที่ไม่ซ้ำของแพลตฟอร์มเว็บของเรา ซึ่งก็คือ https://vr.with.in/ ใครก็ตามที่มีเบราว์เซอร์ที่เปิดใช้ VR สามารถไปที่ไซต์ คลิกปุ่มและสวมชุดหูฟังเพื่อดื่มด่ำกับพอร์ตโฟลิโอของภาพยนตร์ VR ของเรา

ซึ่งรวมถึงแต่ไม่จำกัดเพียง Chrome ใน Daydream View ดูข้อมูลเกี่ยวกับอุปกรณ์และจอแสดงผลแบบติดศีรษะได้ที่ https://webvr.info/

เว็บมักจะใช้การนำเสนอฉากแบบ 3 มิติเป็นหลัก เช่นเดียวกับสภาพแวดล้อมการแสดงผลแบบ Virtual Reality อื่นๆ ฉากนี้มีกล้อง มุมมองของคุณ และวัตถุต่างๆ ในการจัดการฉาก กล้อง และวัตถุนี้ เราใช้ไลบรารีที่เรียกว่า Three.js ซึ่งใช้ประโยชน์จากองค์ประกอบ <canvas> เพื่อโยนการแสดงผลไปยัง GPU ของคอมพิวเตอร์ มีส่วนเสริม Three.js ที่มีประโยชน์จำนวนมาก ที่จะทำให้ผู้ชมสามารถดูฉากได้ใน WebVR 2 องค์ประกอบหลักคือ THREE.VREffect สำหรับการสร้างวิวพอร์ตสำหรับตาแต่ละข้าง และ THREE.VRControls สำหรับการแปลมุมมอง (เช่น การหมุนและตำแหน่งของจอแสดงผลแบบติดศีรษะ) ให้เข้ามาในฉากอย่างน่าประหลาดใจ ตัวอย่างวิธีติดตั้งใช้งานมีมากมาย ดูตัวอย่าง WebVR ของ Three.js สำหรับวิธีเริ่มต้นใช้งาน

ขณะที่เราสำรวจ WebVR ลึกขึ้น ก็พบปัญหาบางอย่าง ถ้าเราดูเนื้อหาของเว็บ ข้อความก็เป็นส่วนสำคัญ แม้เนื้อหาส่วนใหญ่ของเราจะเป็นวิดีโอ แต่หากคุณไปที่ข้อความภายในเว็บไซต์จะล้อมรอบเนื้อหาอยู่ อินเทอร์เฟซผู้ใช้และข้อมูลเพิ่มเติมเกี่ยวกับภาพยนตร์หรือภาพยนตร์ที่เกี่ยวข้องทั้งหมดสร้างขึ้นด้วยข้อความ นอกจากนี้ ข้อความทั้งหมดนี้จะสร้างขึ้นใน DOM การสำรวจ WebVR และ https://vr.with.in/ ทั้งหมดของเราอยู่ใน <canvas>

ข้อความที่ใช้ใน WebVR ข้อความที่ใช้ใน WebVR
ข้อความที่ใช้ใน WebVR สำหรับ vr.with.in

ฉันจะมีตัวเลือกใดบ้าง

โชคดีที่เรามีงานที่ต้องทำเพื่อให้สิ่งนี้เกิดขึ้นได้ จากการวิจัย เราพบว่าวิธีที่มีประสิทธิภาพจำนวนมากในการแสดงผลข้อความในสภาพแวดล้อมแบบ 3 มิติในองค์ประกอบ <canvas> ด้านล่างนี้เป็นเมทริกซ์บางส่วนที่เราพบ ข้อดีและข้อเสียของแต่ละส่วน

ไม่เกี่ยวข้องกับการแก้ปัญหา ฟีเจอร์ตัวอักษร การแสดง ติดตั้งใช้งานได้ง่าย
ข้อความ Canvas 2 มิติ มี มี มี
ข้อความเวกเตอร์แบบย่อ มี มี
ข้อความ 3 มิติแบบอัด มี
ข้อความบิตแมปของช่องระยะทางที่ลงนาม มี มี มี

การตัดสินใจของเรา: แบบอักษรบิตแมป SDF

Canvas 2 มิติที่ใช้ ctx.fillText() สามารถช่วยตัดข้อความ ระยะห่างตัวอักษร และความสูงบรรทัดได้ แต่ส่วนที่เกินมาจะถูกตัดออก และข้อความจะเบลอหากคุณซูมเข้าไกลมากๆ คุณสามารถเพิ่มขนาดของพื้นผิว Canvas แต่ขนาดพื้นผิวอาจถึงขีดจํากัดสูงสุด หรืออาจมีประสิทธิภาพลดลงหากพื้นผิวใหญ่เกินไป

โดยพื้นฐานแล้วข้อความ 3 มิติที่อัดออกมานั้นเหมือนกับข้อความเวกเตอร์แบบสามเหลี่ยม แต่มีความชัดลึกและอาจเป็นแนวนูน เพื่อให้มีรูปเรขาคณิตอย่างน้อย 2 เท่า ชื่อหรือโลโก้เหล่านี้สามารถใส่ลงในขนาดเล็กๆ สำหรับชื่อหรือโลโก้ได้ แต่จะทำงานได้ไม่ดีสำหรับข้อความจำนวนมาก และไม่มีฟีเจอร์การพิมพ์

เวิร์กโฟลว์ของแบบอักษรเป็น SDF บิตแมป
เวิร์กโฟลว์บิตแมปของแบบอักษรเป็น SDF

แบบอักษรบิตแมปใช้รูปสี่เหลี่ยมจัตุรัส 1 รูป (สามเหลี่ยม 2 รูป) ต่ออักขระ ดังนั้นจึงใช้เรขาคณิตน้อยกว่าและทำงานได้ดีกว่าเวกเตอร์ที่ตัดเศษ ภาพเหล่านี้ยังคงเป็นแบบแรสเตอร์เพราะใช้สไปรท์แผนที่พื้นผิว แต่ด้วยตัวไล่เฉดสี SDF โมเดลเหล่านี้จึงไม่ขึ้นอยู่กับความละเอียด จึงดูดีกว่าพื้นผิวแคนวาสแบบ 2 มิติ Matt DesLauriers ข้อความ 3 Bmfont ของ Matt DesLauriers ยังรวมถึงฟีเจอร์การพิมพ์ที่เชื่อถือได้สำหรับการตัดข้อความ ระยะห่างตัวอักษร ความสูงของบรรทัด และการจัดข้อความด้วย ไม่ต้องตัดส่วนที่เกินมา ขนาดแบบอักษรจะควบคุมด้วยการปรับขนาด เราเลือกวิธีนี้เพราะให้ตัวเลือกที่ดีที่สุดในการออกแบบ และยังคงประสิทธิภาพในการทำงาน แต่น่าเสียดายที่วิธีนี้ไม่ได้ง่ายเท่าที่ควร เราจึงจะทำตามขั้นตอนต่างๆ โดยหวังว่าจะเป็นการช่วยเหลือเพื่อนนักพัฒนาซอฟต์แวร์ที่ทำงานเกี่ยวกับ WebVR ได้

1. สร้างแบบอักษรบิตแมป (.png + .fnt)

อินเทอร์เฟซ Hiero
อินเทอร์เฟซ Hiero
เอาต์พุต Hiero (ไฟล์ Bitmap PNG และ .fnt) เอาต์พุต Hiero (ไฟล์ Bitmap PNG และ .fnt)
เอาต์พุต Hiero (ไฟล์ PNG และ .fnt บิตแมป)

Hiero เป็นเครื่องมือแพ็กแบบอักษรบิตแมปที่ทำงานกับ Java เอกสาร Hiero ไม่ได้อธิบายวิธี เรียกใช้งานโดยไม่ต้องผ่านกระบวนการสร้างที่ซับซ้อน ก่อนอื่น ให้ติดตั้ง Java หากยังไม่ได้ติดตั้ง จากนั้น หากดับเบิลคลิก Runnable-hiero.jar ไม่เปิด Hiero ให้ลองเรียกใช้ด้วยคำสั่งนี้ในคอนโซล

java -jar runnable-hiero.jar

เมื่อ Hiero ทำงาน ให้เปิดแบบอักษรบนเดสก์ท็อป .ttf หรือ .otf ป้อนอักขระที่คุณต้องการรวมไว้ เปลี่ยนการแสดงผลเป็น Java เพื่อเปิดใช้เอฟเฟกต์ เพิ่มขนาดเพื่อให้อักขระแสดงเต็มพื้นที่สี่เหลี่ยมของแคชรูปทั้งหมด เพิ่มเอฟเฟกต์ฟิลด์ระยะทาง ปรับขนาดและการกระจายของฟิลด์ระยะทาง ค่ามาตราส่วนเหมือนกับความละเอียด ยิ่งภาพสูงมากเท่าใด ก็ยิ่งเบลอน้อยลงเท่านั้น แต่ยิ่งต้องใช้เวลานานขึ้นเพื่อให้ Hiero แสดงภาพตัวอย่าง แล้วบันทึกแบบอักษรบิตแมป เครื่องมือจะสร้างแบบอักษรบิตแมปที่ประกอบด้วยรูปภาพ .png และไฟล์คำอธิบายแบบอักษร AngelCode .fnt

2. แปลง AngelCode เป็น JSON

เมื่อสร้างแบบอักษรบิตแมปแล้ว เราต้องโหลดแบบอักษรดังกล่าวลงในแอป JavaScript โดยใช้แพ็กเกจ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. ข้อความ 3 Bmfont ที่ใช้เบราว์เซอร์

เมื่อเราโหลดแบบอักษรแล้ว ข้อความ 3 ตัวอักษรของ Matt จะจัดการกับส่วนที่เหลือ เนื่องจากเราไม่ได้ใช้ Node กับแอปของเราเอง เราจะไปที่ browserify three-bmfont-text.js เป็น three-bmfont-text-bundle.js ที่ใช้งานได้

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

4. ตัวปรับแสงเงา SDF

ปรับแถบเลื่อน afwidth และ threshold ใน vr.with.in/archive/text-sdf-bitmap/ เพื่อดูผลกระทบของตัวปรับแสงเงาในช่องระยะทาง

5. การใช้งาน

เพื่อความสะดวก เราได้สร้างคลาส Wrapper ของ TextBitmap สำหรับข้อความ 3-bmfont-text แบบเบราว์เซอร์

การทำงานของข้อความ-sdf-bitmap
การทำงานของ Text-sdf-bitmap
<script src="three-bmfont-text-bundle.js"></script>
<script src="sdf-shader.js"></script>
<script src="text-bitmap.js"></script>

สร้างคำขอ XHR สำหรับไฟล์แบบอักษร .json และสร้างออบเจ็กต์ข้อความในโค้ดเรียกกลับ

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 ยังรวม Hitbox ที่มองไม่เห็นสำหรับการโต้ตอบเรย์แคสต์ 3.js ผ่านเมาส์ กล้อง หรือตัวควบคุมการเคลื่อนไหวที่ติดตามด้วยมือ เช่น Oculus Touch หรือตัวควบคุม Vive ขนาด Hitbox จะอัปเดตอัตโนมัติเมื่อคุณเปลี่ยนตัวเลือกข้อความ

มีการเพิ่ม Bmtext.group ลงในโหมด 3.js ถ้าคุณต้องมีสิทธิ์เข้าถึงลูก/ของ Object3D กราฟฉากสำหรับข้อความจะมีลักษณะดังนี้

แผนภาพระบบไฟล์

6. แตกไฟล์ JSON และแก้ไข Xoffset

ภายใน GIF ข้อความ

หากช่องหน้าต่างไม่ปกติ คุณอาจต้องแก้ไข xoffsets ใน json วางไฟล์ JSON ลงใน Jsbeautifier.org เพื่อรับไฟล์เวอร์ชันที่ไม่มีการปรับแต่ง

โดยพื้นฐานแล้ว Xoffset เป็นการจัดช่องไฟส่วนกลางสำหรับอักขระ 1 ตัว เคอร์นิงมีไว้สำหรับอักขระ 2 ตัว ที่ปรากฏติดกัน ค่าเริ่มต้นในอาร์เรย์เคอร์นิงไม่สร้างความแตกต่างเลยและอาจเสียเวลาแก้ไขไม่ได้ คุณสามารถล้างอาร์เรย์นั้นให้ว่างเพื่อลดขนาดไฟล์ของ JSON จากนั้นแก้ไข xoffsets สำหรับการจัดช่องไฟ

ก่อนอื่น คุณจะต้องหาว่าอักขระใดใช้กับรหัสอักขระใดใน 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 ทุกอย่างจะต้องจัดตำแหน่งด้วยตนเอง คล้ายกับการวางตำแหน่งแบบสัมบูรณ์ ทุกองค์ประกอบด้วย CSS ด้วยตัวคุณเอง คุณนึกภาพออกไหมว่าทำสิ่งนี้ใน CSS

    * { position: absolute; }

นี่คือลักษณะการจัดวางข้อความในแบบ 3 มิติ ในมุมมองรายละเอียด: ชื่อ ผู้เขียน คำอธิบาย และระยะเวลา คือออบเจ็กต์ TextBitmap ใหม่ที่มีรูปแบบ สี สัดส่วน ฯลฯ ของตนเอง

เลย์เอาต์ 3 มิติ
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 แต่ละกลุ่มอยู่ในแนวแนวตั้งกับด้านบนของ Mesh ของ TextBitmap (ดูจุดกึ่งกลางในการอัปเดต text-bitmap.js) หากคุณเปลี่ยนข้อความสำหรับวัตถุเหล่านั้นในภายหลัง และความสูงของวัตถุเปลี่ยนแปลง คุณจะต้องคำนวณตำแหน่งเหล่านั้นใหม่ด้วย ซึ่งมีเพียงตำแหน่ง Y ของข้อความเท่านั้นที่ได้รับการแก้ไข แต่โอกาสในการทำงานแบบ 3 มิติได้คือ เราสามารถดันและดึงข้อความในทิศทาง z รวมถึงหมุนรอบแกน x, y และ z ได้ด้วย

บทสรุป

ข้อความและเลย์เอาต์ใน WebVR มีประโยชน์มากเมื่อเทียบกับ HTML และ CSS แม้จะใช้งานง่ายและใช้กันอย่างแพร่หลาย แต่โซลูชันที่ใช้งานได้มีอยู่และคุณสามารถทำสิ่งต่างๆ ใน WebVR ได้มากกว่าในหน้าเว็บ HTML แบบเดิม WebVR มีอยู่ในปัจจุบัน น่าจะมีเครื่องมือที่ดีกว่านี้ในอนาคต ระหว่างนี้ขอให้ลองใช้ แล้วลองทดสอบดู การพัฒนาโดยไม่ใช้เฟรมเวิร์กที่ใช้กันอย่างแพร่หลายจะนำไปสู่โปรเจ็กต์ที่มีเอกลักษณ์ยิ่งขึ้น ซึ่งก็เป็นเรื่องที่น่าตื่นเต้น