- มีการเสนอเทคนิคการเรนเดอร์เวกเตอร์แบบเรียลไทม์รูปแบบใหม่เพื่อแก้ปัญหาคุณภาพของ การเรนเดอร์ข้อความ โดยเฉพาะข้อจำกัดของวิธีแบบ SDF (distance field)
- ส่งข้อมูล glyph (อักขระ) ในรูปเส้นโค้งเวกเตอร์ไปยัง GPU โดยตรงเพื่อทำ การแรสเตอร์ไรซ์แบบเรียลไทม์ จึงได้ทั้งความละเอียดไม่จำกัดและการใช้หน่วยความจำต่ำ
- ใช้เทคนิค texture atlas และ temporal accumulation เพื่อให้ได้ คุณภาพ anti-aliasing สูง และการแคชที่มีประสิทธิภาพ
- สามารถปรับใช้ให้เหมาะกับ โครงสร้าง subpixel ได้หลากหลายแบบ (เช่น OLED, LCD เป็นต้น) จึงให้ผลลัพธ์ที่นุ่มนวลและคมชัดโดยไม่มีปัญหา fringing (สีฟุ้ง)
- นำเสนอแนวทางที่เรียบง่ายแต่ขยายต่อได้ดีสำหรับ การเรนเดอร์ฟอนต์คุณภาพสูง ในงานอย่างข้อความแบบเรียลไทม์, UI, เกม เป็นต้น
บทนำ: โจทย์ของการเรนเดอร์ข้อความ
- ในการเรนเดอร์ข้อความแบบเรียลไทม์มีปัญหาหลากหลาย เช่น aliasing (รอยหยัก), texture ขนาดใหญ่, เวลา build, การซูมเข้าออก, การเคลื่อนที่ที่ลื่นไหล
- วิธี Multi-Channel Signed Distance Fields (SDFs) ที่นิยมใช้กันก่อนหน้านี้มีข้อจำกัดทั้งด้านคุณภาพและความยืดหยุ่น
- จากปัญหา โครงสร้าง subpixel ที่ไม่เป็นมาตรฐาน ของจอ OLED รุ่นใหม่และปัญหา fringing จึงพัฒนาแนวทางใหม่ที่คำนึงถึง subpixel anti-aliasing ด้วย
ข้อจำกัดของวิธี SDF แบบเดิม
คุณภาพ
- ในวิธี SDF หากเป็นฟอนต์ที่มี รายละเอียดเล็กมาก หรือมี เส้นบาง จำนวนมาก จะเกิดปัญหาคุณภาพลดลงและข้อมูลสูญหาย
- หากไม่เพิ่มความละเอียด ก็จะยังมี artifact หลงเหลือใน glyph บางตัว
ขนาด atlas
- SDF ต้องสร้างแบบออฟไลน์ก่อนแล้วเก็บลง atlas ซึ่งในกรณีที่มี glyph จำนวนมากหรือฟอนต์ CJK (จีน ญี่ปุ่น เกาหลี) ขนาดจะใหญ่จนแทบใช้งานจริงไม่ได้
- หากใช้หลายฟอนต์พร้อมกัน ภาระด้านหน่วยความจำและแบนด์วิดท์สำหรับการสตรีมจะสูงมาก
ความยืดหยุ่นและความเรียบง่าย
- การมีขั้นกลางอย่าง SDF ทำให้ทั้งกระบวนการตั้งแต่ข้อมูลต้นทางไปจนถึงผลลัพธ์สุดท้ายซับซ้อนขึ้น
- มีข้อจำกัดมากในการ นำภาพเวกเตอร์แบบเรียลไทม์หรือแบบไดนามิกมาใช้หรือแก้ไขโดยตรง
แนวทางใหม่: แรสเตอร์ไรซ์เส้นโค้งเวกเตอร์แบบเรียลไทม์
- แทนที่จะสร้าง texture ไว้ล่วงหน้า จะส่ง ข้อมูลเส้นโค้งเวกเตอร์ของ glyph ที่มองเห็นอยู่จริงบนหน้าจอ (เช่น เส้นโค้งเบซิเยร์) ไปยัง GPU โดยตรง แล้วแรสเตอร์ไรซ์ ณ จุดนั้น
- ใส่ glyph ลงใน atlas texture เท่าที่จำเป็น และคงไว้หรือปล่อยออกตามความถี่ในการใช้งาน
- ตราบใดที่ glyph ยังอยู่บนหน้าจอ จะใช้ การสะสมตัวอย่าง (temporal accumulation) เพื่อให้ได้ ผลลัพธ์แบบ anti-aliased ที่ลื่นและมีคุณภาพสูงมาก
- เนื่องจากประมวลผลแบบ เวกเตอร์ ตลอดเวลา จึงให้ผลลัพธ์ที่คมชัดโดยไม่มีข้อจำกัดด้านความละเอียด
การจัดการข้อมูลเส้นโค้งของฟอนต์
- ใช้ไลบรารีโอเพนซอร์สอย่าง FreeType เพื่ออ่านฟอร์แมตฟอนต์หลากหลายแบบและดึงข้อมูลเส้นโค้งของ glyph ออกมา
- แยกวิเคราะห์ glyph เป็น เส้นตรง, เส้นโค้งเบซิเยร์กำลังสอง/กำลังสาม แล้วแปลงเส้นโค้งทั้งหมดให้เป็นเส้นโค้งเบซิเยร์กำลังสองเพื่อให้ GPU shader ประมวลผลง่ายขึ้น
- เส้นตรงจะถูกแปลงเป็นเส้นโค้งกำลังสองโดยเพิ่มจุดควบคุมตรงกลาง
- เส้นโค้งกำลังสามจะแบ่งเป็นเส้นโค้งกำลังสอง 2 ช่วง
การคำนวณ coverage (การเติมพื้นที่ภายในพิกเซล)
- ในแต่ละพิกเซลจะคำนวณ จุดตัดระหว่างเส้นโค้งกับรังสีในแนวนอน แล้วใช้ winding number (จำนวนจุดตัดสะสม) เพื่อตัดสินว่าอยู่ด้านในหรือด้านนอก
- มีการรวม ตัวอย่างจำนวนมาก (สะสมตัวอย่าง n ครั้ง) โดยความคลาดเคลื่อนเล็กน้อยบางส่วนแทบไม่ส่งผลต่อผลลัพธ์สุดท้าย
- ใช้เทคนิค การจัดวางจุดตัวอย่าง (quasirandom sequence) เพื่อสะสมผลลัพธ์จากตำแหน่งที่หลากหลายในแต่ละเฟรม
การปรับให้การเข้าถึงเส้นโค้งมีประสิทธิภาพ
- แบ่ง glyph ออกเป็น band แนวนอน แล้วทดสอบเฉพาะเส้นโค้งที่เกี่ยวข้องในแต่ละ band เพื่อลดปริมาณการคำนวณ
- ใช้ การจัดวาง thread และการวนซ้ำระดับ band เพื่อเพิ่มประสิทธิภาพของการประมวลผลแบบ bulk บน GPU ให้สูงสุด
การแพ็กและจัดการ atlas
- จัดสรรและบริหารภาพ glyph แต่ละตัวภายใน atlas (texture ร่วม)
- glyph ที่ยังไม่มีจะจัดสรรพื้นที่ใหม่แล้วแรสเตอร์ไรซ์ ส่วน glyph ที่มีอยู่แล้วจะนำกลับมาใช้ซ้ำ
- ทั้งนี้ แม้จะเป็น glyph เดียวกันก็อาจต้องมีหลายเวอร์ชันตาม ตำแหน่ง subpixel และขนาด
- ใช้ Z-Order Packing (เช่น Morton code) เพื่อทำการแพ็กระหว่างบิตเซตแบบหนึ่งมิติกับพื้นที่ 2D อย่างมีประสิทธิภาพ
- สามารถประยุกต์อย่างยืดหยุ่นตามโครงสร้างของภาษา เช่น กลุ่มอักษรละตินเน้นแนวตั้ง กลุ่มอักษรอาหรับเน้นแนวนอน เป็นต้น
- เมื่อ glyph ไม่จำเป็นต้องใช้อีก ก็สามารถจัดสรรพื้นที่ใน atlas นั้นใหม่ได้
การสะสมตามเวลา (Temporal Accumulation)
- ผ่านวิธีแคช glyph และการสะสมตัวอย่าง หลังแสดงผลทันทีจะเก็บตัวอย่างคุณภาพสูงได้อย่างรวดเร็ว และค่อยปรับละเอียดขึ้นในเฟรมถัดไป
- เฟรมแรกใช้ 8 samples/pixel จากนั้นค่อย ๆ ลดจำนวนตัวอย่างลง โดยสะสมได้สูงสุด 512 ครั้ง
- ทำให้ได้ทั้ง การแสดง glyph ที่ลื่นไหล และการใช้ทรัพยากรอย่างเหมาะสม
Subpixel anti-aliasing และการป้องกัน fringing
- จัดสรรพื้นที่การเรนเดอร์ในระดับ subpixel (มององค์ประกอบอย่าง RGB แต่ละตัวเป็นหนึ่ง sample) เพื่อเพิ่มความละเอียดในแนวนอน
- รองรับได้ทั้งโครงสร้างมาตรฐานของ LCD และการจัดเรียงแบบต่าง ๆ ของ OLED/WOLED
- ให้เอฟเฟกต์ที่ลื่นไหลโดยไม่มี fringing (สีฟุ้ง)
- เมื่อจัดเรียงให้ตัวอย่าง subpixel ซ้อนทับกัน (Overlapping) ก็สามารถสะท้อน ผลการผสมแสงของจอจริง ได้ด้วย
- จึงให้ผลลัพธ์ที่เป็นธรรมชาติและคมชัดได้แม้ไม่มีขอบพิกเซลหรือ hinting
ความสำคัญของแนวทางตามโครงสร้าง subpixel ของแต่ละจอ
- หากสามารถ ตรวจสอบข้อมูลการจัดเรียง subpixel ของจอภาพด้วยโปรแกรม ได้ ก็จะทำการเรนเดอร์ได้ละเอียดและแม่นยำยิ่งขึ้น
- เน้นว่าปัญหานี้ไม่ใช่ข้อจำกัดของฮาร์ดแวร์ แต่เป็นโจทย์ของการประมวลผลในซอฟต์แวร์
สรุปและแนวโน้มการใช้งาน
- การเรนเดอร์ข้อความที่ดีส่งผลอย่างมากต่อการใช้งานโดยรวมและคุณภาพของบริการ
- โดยเฉพาะใน UI/เกม การแสดงผลฟอนต์คุณภาพสูงสามารถสร้างความแตกต่างอย่างมากต่อประสบการณ์ของผลิตภัณฑ์
- เป็นโครงสร้างการทำงานที่ทำให้หลักการ เรียบง่าย, ขยายต่อได้, คุณภาพสูง, ยืดหยุ่น เกิดขึ้นจริงได้
- ทั้งการทำเป็นโอเพนซอร์สและการรองรับ subpixel ที่หลากหลาย ทำให้ เหมาะอย่างยิ่งต่อการใช้งานจริงในอุตสาหกรรม/โปรดักชัน
1 ความคิดเห็น
ความเห็นจาก Hacker News