รหัสนี้ช่วยให้คุณแสดงข้อความประสิทธิภาพสูงในแอปพลิเคชัน OpenGL ของคุณเอง ห้องสมุดการเรนเดอร์แบบอักษรได้รับการออกแบบอย่างง่ายดายและแสดงประสิทธิภาพในใจ ฉันเขียนใน ~ 2010 และอัปเดตทุก ๆ ครั้ง ไฟล์ตัวอักษรที่อ่านโดยไลบรารีนี้เป็นไปตามรูปแบบที่พัฒนาขึ้นสำหรับเครื่องกำเนิด BM Font: http://angelcode.com/products/bmfont/ ไฟล์ฟอนต์มาพร้อมกับไฟล์พื้นผิว ห้องสมุดรองรับพื้นผิว RGBA มาตรฐานรวมถึงช่อง SDF เดียวและแม้แต่ SDF หลายช่องสัญญาณ

คอยติดตาม
ไลบรารีฟอนต์แบ่งออกเป็นไฟล์ต่อไปนี้:
การเรียกใช้ฟังก์ชัน DrawString ทำสิ่งต่อไปนี้: รับสตริง→พาร์สสตริง→สร้างรายการของสี่เหลี่ยม→แปลว่าเป็นอาร์เรย์บัฟเฟอร์จุดสุดยอด -> วาดสามเหลี่ยมที่มีพื้นผิวทั้งหมด ในระหว่างการแยกวิเคราะห์สตริงที่จะวาดจะถูกตรวจสอบสำหรับตัวอักษรที่ไม่สามารถวาดได้โดยแบบอักษรปัจจุบันตัวอักษรเหล่านั้นจะถูกวาดเป็นเครื่องหมายคำถาม สำหรับตัวละครแต่ละตัวในสตริงรูปสี่เหลี่ยมจะถูกสร้างและเพิ่มเข้าไปในรูปสี่เหลี่ยมจัตุรัสสุดท้ายสี่เหลี่ยมจัตุรัสนี้มีข้อมูลเกี่ยวกับตำแหน่งและขนาดบนหน้าจอ (2D, orthogonal!) และพิกัดพื้นผิวสำหรับอักขระตัวหนึ่งภายในตัวอักษรบิตแมป ตำแหน่งของรูปสี่เหลี่ยมขึ้นอยู่กับตำแหน่งเริ่มต้นของสตริงและตำแหน่งของอักขระก่อนหน้า ความสัมพันธ์เฉพาะระหว่างระยะห่างของตัวละครหนึ่งตัวและตัวต่อไปเรียกว่า kerning ไฟล์การกำหนดค่าตัวอักษรมีตารางที่มีข้อมูล kerning ทั้งหมดสำหรับแบบอักษรที่เฉพาะเจาะจงนั้น เช่นอาจเป็นไปได้ว่าถ้า "A" ตามด้วย "M" มันจะต้องห่างกันหนึ่งพิกเซล แต่เมื่อ "O" ตามด้วย "M" มันจะลบด้วยพิกเซลหนึ่งพิกเซลหรือพิกเซลเป็นศูนย์ ข้อมูลเหล่านี้จะถูกเก็บไว้ภายในในอาร์เรย์สองมิติสำหรับการเข้าถึงที่รวดเร็ว เพื่อให้ภาพวาดนี้เร็วพอข้อมูลทั้งหมดเกี่ยวกับตัวละครและความสัมพันธ์ของตัวละคร (เช่น kerning) รวมถึงพื้นผิวจะถูกโหลดเมื่อเริ่มโปรแกรม สามารถจัดเก็บข้อความเพื่อไม่ต้องสร้างบัฟเฟอร์จุดสุดยอดในการวนซ้ำการเรนเดอร์แต่ละครั้ง
วิธีที่ง่ายที่สุดในการตรวจสอบว่าห้องสมุดทำงานอย่างไรและคุณสามารถใช้งานได้อย่างไรในโครงการของคุณคือการตรวจสอบการใช้งานตัวอย่างที่มาพร้อมกับ repo นี้ ในกรณีที่คุณต้องการข้อมูลเพิ่มเติมโปรดอ่านบทที่เหลือของบทนี้
คุณจะต้องคัดลอก 10 ไฟล์ที่กล่าวถึงใน Overiew ลงในโฟลเดอร์โครงการของคุณ
ในรหัสของคุณสร้างวัตถุห้องสมุดแบบอักษรทั่วโลกก่อนที่จะเปิดบริบทการแสดงผลเช่น SO:
// load openGL fonts
m_fontLibrary = new CFontLibrary(<PathToFontFolder>);
if (!m_fontLibrary-> ParseAllFontsInFolder ())
return; // no fonts found!สิ่งนี้จะโหลดฟอนต์ทั้งหมดที่เก็บไว้ในโฟลเดอร์ที่คุณระบุเป็นพารามิเตอร์อินพุต หลังจากสร้างบริบทการเรนเดอร์แล้วพื้นผิวจะต้องโหลดเช่นนั้น:
// init font library from the current rendering context!
theApp.m_fontLibrary-> InitGLFonts ();สิ่งนี้สามารถทำได้ในฟังก์ชั่น init เดียวของบริบทการแสดงผลนั้น โปรดทราบว่าคุณไม่สามารถแบ่งปันพื้นผิวระหว่างสองบริบทขึ้นไปกับห้องสมุดนี้ (ฉันไม่ได้นำไปใช้เพราะในเวลานั้นไม่มีวิธีที่มีประสิทธิภาพในการทำมันมีเพียงการ์ด Nvidia เท่านั้นที่สามารถทำได้ ดังนั้นคุณต้องเรียกสิ่งนี้สำหรับบริบทการแสดงผลใหม่แต่ละบริบท เมื่อทำสิ่งนี้เสร็จแล้วไลบรารีฟอนต์ก็พร้อมใช้งานซึ่งหมายความว่าคุณสามารถเรียกวิธีการ DrawString () จากวัตถุ FontLibrary
(หมายเหตุ: บทนี้ต้องการการยกเครื่องซึ่งถูกต้องเพียงอย่างเดียวพารามิเตอร์ฟังก์ชั่นบางอย่างหายไป แต่ส่วนใหญ่อธิบายตนเองได้) ส่วนหัวของการเรียกใช้การเรียกใช้:
void DrawString ( const std::string& textToDraw, int x, int y, float color[ 4 ], const std::string& font, float scale = 1 . 0f );พารามิเตอร์อธิบายไว้ด้านล่างในตาราง
| พารามิเตอร์ | คำอธิบาย |
|---|---|
| const std :: string & textTodraw | สตริงที่จะวาดเป็น std :: string ตัวอักษรที่ไม่รู้จักถูกวาดเป็น '?' อักขระใดที่ถูกต้องขึ้นอยู่กับตัวอักษรที่ใช้และสามารถกำหนดได้เมื่อสร้างฟอนต์บิตแมป |
| int x | ตำแหน่ง X ของจุดเริ่มต้นของสตริงในพิกัดหน้าจอ 0 - ความกว้าง |
| int y | ตำแหน่ง y ของจุดเริ่มต้นของสตริงในพิกัดหน้าจอ 0 - ความสูง |
| สีลอย [4] | อาร์เรย์ลอยที่มีข้อมูลสีที่จะใช้ในการปรับเปลี่ยนพื้นผิว ข้อมูลสีคือค่าจาก 0.0 ถึง 1.0 (รวม) ในลำดับมาตรฐานต่อไปนี้: {r, g, b, alpha} เห็นได้ชัด .. |
| const std :: string & font | พารามิเตอร์นี้กำหนดประเภทตัวอักษรที่จะใช้ สามารถใช้แบบอักษรแบบอักษรเท่านั้นที่อยู่ในโฟลเดอร์และอยู่ที่นั่นในเวลาโหลด คุณอาจส่งผ่านชื่อไฟล์ของแบบอักษรนั้นโดยไม่มีส่วนขยายหรือสำหรับการอ่านรหัสเพิ่มเติมและความปลอดภัยใช้การกำหนดจากไฟล์: fontlibrary.h หมายเหตุ: หากคุณต้องการพิมพ์ตัวหนาหรือตัวเอียงคุณต้องใช้แบบอักษรที่ตั้งค่าให้ทำเช่นนั้น |
| สเกลลอย | สำหรับพื้นผิว RGBA ขอแนะนำให้ใช้ค่าเริ่มต้น: 1.0F คุณสามารถปรับขนาดขึ้นหรือลงได้ แต่ควรชัดเจนว่าสิ่งนี้จะส่งผลให้เบลอ อย่างไรก็ตามด้วย SDF และ MSDF คุณควรจะสามารถขยายขนาดขึ้นและลงได้อีกก่อนที่จะเห็นสิ่งประดิษฐ์ |
โปรดทราบว่ามีฟังก์ชั่นเพิ่มเติมพร้อมคุณสมบัติเพิ่มเติมเช่นตัวแบ่งบรรทัดอัตโนมัติ ดูไฟล์ส่วนหัวของไลบรารีตัวอักษร โปรดทราบว่าสตริงที่จะวาดจะถูกตัดออกหลังจาก 10922 อักขระ หากคุณต้องการอักขระมากขึ้นไม่ว่าจะด้วยเหตุผลแปลก ๆ เพียงแค่ใช้การเรียกใช้การดึงเพิ่มเติมและแบ่งสตริงออกเป็นชิ้นส่วน
บทนี้เกี่ยวข้องกับการเพิ่มแบบอักษรของคุณเองในห้องสมุดตัวอักษร
โปรดทราบว่าฉันมุ่งเน้นไปที่แบบอักษรที่ไม่ใช่ SDF ที่นี่ ขั้นตอนสำหรับแบบอักษร SDF นั้นค่อนข้างคล้ายกัน แต่ BM-Font-Gen ไม่เพียงพอ คุณยังสามารถใช้เครื่องมือนั้นได้ แต่คุณจะต้องดำเนินการโพสต์ขั้นตอนการประมวลผลด้วยเครื่องมือเช่น ImageMagick การสอนด้านล่าง
จำเป็นต้องมีเพียงสามขั้นตอนในการรวมตัวอักษรใหม่: 1 สร้าง Font-Config และ Font-Bitmap โดยใช้ BM-Font-Generator 2. คัดลอกไฟล์ที่ได้สองรายการลงในโฟลเดอร์ FONTS ของคุณ 3 (ไม่บังคับ) เพิ่มฟอนต์สตริง
ในส่วนต่อไปนี้การใช้ BM-Font Generator มีการอธิบายอย่างละเอียด แต่มีบันทึกย่อก่อน ไฟล์ฟอนต์แต่ละตัวที่คุณผลิตมีเพียงฟอนต์ที่มีขนาดคงที่และมีการกำหนดไว้แล้วโดยไฟล์ไม่ว่าจะเป็นตัวหนาหรือตัวเอียง ฯลฯ นับจำนวนเดียวกันสำหรับโครงร่างความราบรื่นของตัวอักษร ฯลฯ เรื่องนี้จะชัดเจนขึ้นในส่วนต่อไปนี้
สำหรับการผลิต Font-Config เช่นเดียวกับบิตแมปแบบอักษรจริงฉันใช้“ Bitmap Font Generator” จาก AngelCode ซึ่งสามารถรับได้จากเว็บไซต์ของพวกเขา: http://angelcode.com/products/bmfont/ หลังจากการติดตั้งให้เปิดโปรแกรมแล้วควรมีลักษณะเหมือนในรูปต่อไปนี้

เป็นขั้นตอนแรกให้เปิดการตั้งค่าแบบอักษรโดยคลิกที่ตัวเลือก→การตั้งค่าตัวอักษรหรือโดยการกดปุ่ม [F] ซึ่งจะเปิดหน้าต่างใหม่ดังที่แสดงโดยตัวเลขถัดไป

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

ตามกฎพื้นฐานให้เลือกอักขระที่คุณมีแนวโน้มที่จะใช้สิ่งนี้จะช่วยประหยัดเวลาในการประมวลผลและหน่วยความจำส่วนใหญ่ทั้งหมดไม่ใช่แค่ตัวละครตัวเดียว แต่มีอีกมาก (kerning ขนาดบิตแมปขนาดอาร์เรย์ในรหัสของเรา ฯลฯ ) หลังจากที่คุณเลือกอักขระทั้งหมดตัวอักษรของคุณจะต้องรวมไปยังส่วนถัดไป
ตอนนี้ถึงเวลาที่จะส่งออกฟอนต์เป็นบิตแมปและสร้างไฟล์กำหนดค่าสำหรับมัน เปิดตัวเลือกการส่งออกของฉันกดปุ่ม [t] หรือตัวเลือกคลิก→ตัวเลือกการส่งออก หน้าต่างใหม่ควรปรากฏขึ้นโดยดูเหมือนในรูปต่อไปนี้

เมื่อการตั้งค่าเหล่านี้เสร็จสิ้นให้ปิดหน้าต่างและดำเนินการต่อไปยังขั้นตอนต่อไป
เพื่อให้แน่ใจว่าพื้นผิวของคุณไม่ใหญ่เกินไปหรือเล็กเกินไปให้กด [V] ในขณะที่อยู่ในหน้าต่างหลักหรือตัวเลือกคลิก→แสดงภาพ หากชื่อหน้าต่างบอกอะไรก็ได้นอกจาก“ ดูตัวอย่าง 1/1” พื้นผิวของคุณเล็กเกินไปสำหรับตัวละครทั้งหมดของคุณและโปรแกรมจะสร้างบิตแมปมากกว่าหนึ่งตัว ในกรณีนี้ให้เปิดตัวเลือกการส่งออกและเพิ่มขนาดพื้นผิวของคุณ หมายเหตุ: ไม่จำเป็นต้องยกกำลังสองหรือกำลังสองอีกต่อไปนี่เป็นเพียง OpenGL เวอร์ชัน 1 ซึ่งเป็นกรณี อย่างไรก็ตามฉันยังคงแนะนำให้ทำเช่นนี้เนื่องจากฟังก์ชั่นที่เกี่ยวข้องกับพื้นผิวบางอย่างอาจยังได้รับการปรับให้เหมาะสม FontLibrary โดยเจตนาไม่ได้จัดการมากกว่าหนึ่งหน้าหรือพื้นผิวหรือพื้นผิวเพราะนี่หมายถึงการผูก/คลายพื้นผิวในระหว่างการโทรแบบ drawstring ครั้งเดียวซึ่งช้า! ดังนั้นทำให้เป็นหน้าเดียว หากในทางกลับกันคุณจะเห็นว่าตัวละครจะเติมส่วนหนึ่งของบิตแมปเท่านั้นให้ลดขนาดพื้นผิวถ้าเป็นไปได้ แต่นี่ไม่สำคัญเท่ากับวิธีอื่น ๆ เมื่อคุณพอใจกับการใช้พื้นที่พื้นผิวให้ไปยังขั้นตอนต่อไป
ตอนนี้การตั้งค่าทั้งหมดจะมีเวลาในการส่งออกแบบอักษร คลิกที่ตัวเลือก→บันทึก Bitmap-Font เป็น .. ชื่อไฟล์ที่คุณระบุที่นี่จะส่งผลกระทบต่อชื่อสำหรับตัวอักษรในห้องสมุดตัวอักษรดังนั้นเลือกอย่างชาญฉลาด เพื่อความสะดวกและเหตุผลการอ่านฉันขอแนะนำการประชุมการตั้งชื่อต่อไปนี้:
< ตัวเอียง? > <bold> <_ ระบุขนาด?>
นี่คือตัวอย่างบางส่วน:
กดบันทึกเพื่อให้กระบวนการเสร็จสมบูรณ์ สิ่งที่ต้องทำตอนนี้คือการคัดลอกไฟล์สองไฟล์สำหรับแบบอักษรนั้นลงในโฟลเดอร์ฟอนต์ของซอฟต์แวร์ของคุณ คุณสามารถแปลง TGA เป็น PNG ด้วยเครื่องมืออื่นเพียงจำไว้ว่าให้เปลี่ยนส่วนขยายไฟล์ในไฟล์ FNT อย่างถูกต้อง
นี่คือกระบวนการ 3 ขั้นตอน
ขั้นแรกให้ใช้เครื่องกำเนิด BMFONT ตามที่อธิบายไว้ข้างต้น อย่างไรก็ตามจากนั้นใช้การตั้งค่าต่อไปนี้ที่อาจแตกต่างกันในรูปแบบที่คุณเคยใช้มาก่อน
สุดท้ายคุณต้องใช้ ImageMagick (https://imagemagick.org/index.php) หรือเครื่องมือที่คล้ายกันเพื่อแปลงไฟล์พื้นผิวเป็น SDF เมื่อคุณติดตั้ง ImageMagick ให้เรียกใช้ต่อไปนี้จากบรรทัดคำสั่ง (ตัวอย่างสำหรับ Windows Power Shell แต่จะคล้ายกันมากสำหรับ UNIX):
magick convert --% Arial400_0.tga -filter Jinc ( +clone -negate -morphology Distance Euclidean -level 50%,-50% ) -morphology Distance Euclidean -compose Plus -composite -level 45%,55% -resize 25% Arial400_0.png
ต่อไปเราต้องแก้ไขไฟล์ FNT เพิ่มสิ่งต่อไปนี้ลงในส่วนหัวของ FNT มือของฉันก่อนคำจำกัดความของ Chars:
fieldType=sdf
สิ่งนี้จะบอกให้ Font Lib ใช้แชนเนล SDF shader เมื่อใช้แบบอักษรนี้
สำหรับ SDFS แบบหลายช่องคุณไม่สามารถใช้เครื่องกำเนิดฟอนต์ BM ได้แทนที่จะใช้: https://soimy.github.io/msdf-bmfont-xml/ ด้วยเครื่องมือนี้คุณต้องเริ่มต้นจากไฟล์ TTF แต่คุณจะได้รับไฟล์ PNG ปกติ เมื่อติดตั้งแล้วให้เรียกใช้ต่อไปนี้จากบรรทัดคำสั่ง:
msdf-bmfont -o multisdf.png cour.ttf
โปรดทราบว่าคุณสามารถจัดหาขนาดตัวอักษรและพารามิเตอร์อื่น ๆ ผ่านทางคำสั่งได้เช่นกัน
นี่เป็นตัวเลือก: สร้างการกำหนดสำหรับแบบอักษรใหม่แต่ละตัวที่คุณเพิ่มลงใน fontlibrary.h สิ่งนี้ควรทำให้การเข้ารหัสง่ายขึ้น!
// font type defines, string must match the filename without extension in your fonts folder!
# define GLFONT_COURIER42_MSDF " Courier42_msdf "
# define GLFONT_ARIAL20 " Arial20 "
# define GLFONT_DINNEXTLTPROMED_SDF " DINNextLTProMED_SDF ".. เพิ่มการกำหนดของคุณเองที่นี่!