นี่คือการสาธิตข้อความการเรนเดอร์โดยตรงบน GPU โดยใช้เค้าโครงเวกเตอร์ที่กำหนดโดยแบบอักษร
รูปทรงของสัญลักษณ์จะถูกแปลงเป็นรายการของเส้นโค้ง bezier สองส่วน (กำหนดโดยจุดควบคุมของพวกเขา) ซึ่งอัปโหลดไปยัง GPU
รูปสี่เหลี่ยมถูกสร้างขึ้นสำหรับแต่ละสัญลักษณ์และพิกเซล shader กำหนดว่าแต่ละพิกเซลจะอยู่ภายในหรือภายนอกสัญลักษณ์ ในการทำเช่นนี้จำนวนที่คดเคี้ยวของพิกเซลจะถูกคำนวณโดยการตัดรังสีด้วยเส้นโค้ง bezier ในทุกสี่แยกรังสีเข้าหรือออกจากพื้นที่ที่เต็มไปด้วยทิศทางของเส้นโค้ง bezier ที่สัมพันธ์กับรังสี ในทุก ๆ ทางออกหมายเลขที่คดเคี้ยวจะเพิ่มขึ้นหนึ่งรายการและทุกรายการจำนวนที่คดเคี้ยวจะลดลงหนึ่ง หลังจากพิจารณาทางแยกทั้งหมดหมายเลขที่คดเคี้ยวจะไม่เป็นศูนย์หากพิกเซลอยู่ในโครงร่าง
ทิศทางของรังสีไม่สำคัญสำหรับการคำนวณจำนวนที่คดเคี้ยวนี้ แต่คณิตศาสตร์สามารถทำให้ง่ายขึ้นอย่างมากโดยใช้รังสีขนานกับแกน x โดยการลบตำแหน่งตัวอย่างออกจากจุดควบคุมของเส้นโค้ง bezier ระบบพิกัดจะถูกเลื่อนเพื่อให้ต้นกำเนิดของรังสีอยู่ที่
ในการค้นหาจุดตัดระหว่างรังสีและเส้นโค้ง bezier เดี่ยวจำได้ว่าเส้นโค้ง bezier กำลังสองอธิบายโดยสูตรต่อไปนี้ (สำหรับพื้นหลังของเส้นโค้ง Bezier ดูความงามและไพรเมอร์):
รับส่วนประกอบ Y เท่านั้นและใช้เงื่อนไข
ซึ่งสามารถจัดเรียงใหม่เป็น:
เพื่อให้สามารถแก้ไขได้โดยใช้สูตรกำลังสอง:
การทดแทน
สมการกำลังสองอาจมีศูนย์หนึ่งหรือสองวิธี นอกจากนี้ยังแก้ปัญหา
เมื่อมาถึงจุดนี้มีการระบุจุดตัดระหว่างเส้นโค้งเรย์และเบเซียร์ แต่พวกเขายังคงต้องจัดเป็นรายการหรือออก การสาธิตที่จัดทำโดย Dobbie จะคำนวณอนุพันธ์ของเส้นโค้ง bezier อย่างชัดเจนสำหรับแต่ละ
ดังนั้นเส้นโค้ง bezier จะข้ามแกน x ในทิศทางคงที่ในแต่ละสารละลายและรวมกับการประชุมสำหรับการวางแนวของรูปร่าง
วิธีการที่แตกต่างกันในการทำความเข้าใจความสัมพันธ์นี้คือการสังเกตว่าเนื่องจากสัญญาณที่แตกต่างกันที่ใช้ในการแก้ปัญหาและรากสแควร์ไม่เป็นลบ
ถ้าพารามิเตอร์
การต่อต้านนามแฝงตามทิศทางรังสีถูกนำมาใช้โดยพิจารณาจากหน้าต่างขนาดของพิกเซลรอบ ๆ ต้นกำเนิดของรังสี หากสี่แยกตกอยู่ในหน้าต่างนี้จำนวนที่คดเคี้ยวจะถูกเปลี่ยนเฉพาะเล็กน้อยเพื่อคำนวณความครอบคลุมของพิกเซล น้ำหนักเศษส่วนถูกกำหนดโดยระยะทางจากขอบซ้ายของพิกเซล (ซึ่งสอดคล้องกับรังสีที่ชี้ไปทางขวา) โดยการพิจารณาแต่ละส่วนเราจะเห็นว่าสิ่งนี้จะคำนวณความครอบคลุมหนึ่งมิติอย่างแน่นอน
โปรดทราบว่าเราต้องพิจารณาทางแยกเล็กน้อยด้านหลังต้นกำเนิดของรังสีในขณะนี้ แต่การใช้งานครั้งแรกจะคำนวณการแยกใด ๆ กับแกน x จากนั้นตรวจสอบตำแหน่ง X ดังนั้นมันจึงไม่เปลี่ยนแปลงมากนัก วิธีคิดที่แตกต่างกันคือเงื่อนไข
สำหรับการต่อต้านนามแฝงอย่างเต็มรูปแบบเราสามารถใช้รังสีหลายตัวตามทิศทางที่แตกต่างกัน (เช่นหนึ่งตามแนวแกน x และหนึ่งตามแนวแกน y)
เทคนิคประเภทนี้ขึ้นอยู่กับสิ่งประดิษฐ์จากความแม่นยำเชิงตัวเลขที่ จำกัด ของตัวเลขจุดลอยตัว ภาพด้านล่างแสดงอินสแตนซ์ของสิ่งประดิษฐ์ดังกล่าวเมื่อซูมเข้าอย่างเต็มที่ (และรู้ว่าจะดูที่ไหน) อย่างไรก็ตามฉันพบว่าการใช้งานนี้มีความเสถียรเชิงตัวเลขอยู่แล้ว สิ่งประดิษฐ์ที่เหลือใด ๆ สามารถกำจัดได้โดยใช้อัลกอริทึม Slug ซึ่งไม่ได้ถูกนำมาใช้ที่นี่เนื่องจากสิทธิบัตรที่เกี่ยวข้อง
การสาธิตนี้ยังไม่ได้ใช้การเพิ่มประสิทธิภาพประสิทธิภาพใด ๆ (เช่นแถบ) และอาจมีการใช้ GPU สูงในบางสถานการณ์และเมื่อใช้แบบอักษรที่ซับซ้อนมาก

โคลนโครงการซ้ำเพื่อเริ่มต้น submodules สำหรับการพึ่งพา (หรือเรียกใช้ git submodule update --init หากคุณได้โคลน repo แล้ว):
git clone --recursive https://github.com/GreenLightning/gpu-font-rendering.git
cd gpu-font-rendering
# Note: CMake will create the build directory.
cmake -S . -B build
make -j8 --directory build
บน Windows คุณอาจต้องการใช้ CMake GUI และ/หรือ Visual Studio แทน
บน Linux คุณอาจต้องติดตั้งแพ็คเกจเพิ่มเติมสำหรับการพัฒนา OpenGL (เช่น sudo apt-get install xorg-dev libgl1-mesa-dev สำหรับ Ubuntu)
./build/main
โปรแกรมต้องการไดเรกทอรี fonts และ shaders เพื่ออยู่ในไดเรกทอรีปัจจุบันเพื่อโหลดทรัพยากร หากคุณได้รับเพียงหน้าต่างสีดำ นี่น่าจะเป็นปัญหามากที่สุด ตรวจสอบไดเรกทอรีการทำงานของคุณและตรวจสอบข้อผิดพลาดคอนโซล
ทดสอบบน Windows 10, MacOS Monterey และ Ubuntu 22.04