Pixi.js: Proposal: Meningkatkan rendering teks

Dibuat pada 5 Apr 2020  ·  27Komentar  ·  Sumber: pixijs/pixi.js

Komunitas telah mengatakannya - kinerja rendering teks Pixi perlu ditingkatkan. Masalah ini dikhususkan untuk bagaimana kami dapat meningkatkan dan apa yang menurut saya akan menjadi cara terbaik untuk menyampaikan:

@bigtimebuddy dan saya membahas metode ini dan kami pikir pendekatan ketiga adalah yang terbaik karena:

  • SDF membutuhkan atlas yang dibuat sebelumnya. Menghasilkan SDF multi-saluran sangat rumit (jika kita ingin melakukannya saat runtime).

  • VTM terlalu rumit untuk font saja.

  • Kurva bezier yang tepat hanya mengharuskan Anda untuk merender font sebagai jalur seperti yang lainnya di Grafik.

Komentar yang paling membantu

@eXponenta tolong berhenti bersikap bermusuhan. Kami sedang menjajaki pendekatan yang belum ada yang solid. Harap konstruktif dan tidak menggunakan penghinaan.

Semua 27 komentar

Hal ini tidak harus di inti.
Ini adalah paket yang berat dan HARUS diimplementasikan di luar paket utama, tim inti tidak perlu khawatir tentang implementasinya.

Pixi SDF adalah contoh yang tepat.

Tolong, jangan coba buat Phaser dari PIXI

Saya ingin memberikan lebih banyak konteks. Saya telah meminta @SukantPal untuk meneliti pendekatan Teks/BitmapText alternatif yang memiliki pertukaran yang berbeda. Khususnya, jika kita dapat menemukan sesuatu yang berkinerja lebih baik daripada Teks dan tampak hebat.

Saya pikir ada beberapa pendekatan di sini. Beberapa mungkin sesuai sebagai plugin bagian ke-3, beberapa mungkin dalam repo tetapi tidak dibundel, dan beberapa mungkin mengganti/menambah API saat ini. Mari kita cari tahu apa pendekatan rendering Teks yang paling bermanfaat yang mengoptimalkan kinerja tetapi dengan sedikit pertukaran ke BitmapText.

Ada beberapa kriteria yang saya gunakan untuk menilai objek tampilan Teks yang bagus:

  • Performa Runtime yang Baik - Merender teks dan mengubah teks berbiaya rendah
  • Memori rendah - penggunaan RAM rendah
  • Ketergantungan Kecil - ukuran file tapak ketergantungan kecil
  • Great Fidelity - bekerja dengan baik dengan resolusi yang berbeda
  • Gaya fleksibel - dukungan untuk goresan, bayangan jatuh, gradien
  • Mendukung Bahasa Glyph Besar - Misalnya, Cina, Jepang, Korea
  • Kompatibel dengan mundur - Bekerja dengan Context2D

| | Performa | Memori | Ketergantungan | Kesetiaan | Penataan | CJK | Konteks2d |
|--|--|--|--|--|--|--|--|
|Teks| | | 👍 | 👍 | 👍 | 👍 | 👍 | 👍 |
|BitmapTeks| 👍 | | 👍 | | | | 👍 |

Baik.
Menjelaskan fragment interpolation dan semua implementasi non-asli:

  1. Membutuhkan shader ekstra dan data ekstra - itu akan mencegah batching.
  2. Perlu membangun kembali geometri saat berubah (hal.3).
  3. Memerlukan tabel mesin terbang untuk semua mesin terbang yang ada dalam bahasa, yang memerlukan memuat TTF khusus ke memori secara total, karena tidak dapat mendukung streaming, lalu menguraikannya. Sepertinya sebagai SWF.
    Karena kami tidak dapat memuat font sistem sebagai bentuk - kami tidak dapat menggunakannya.
  4. Aturan khusus bahasa dipindahkan ke tim lib dari tim browser, yang menerapkan aturan render: ltr/rtl, aturan penggabungan mesin terbang hindi/arab, dll... sama seperti memindahkan 10% browser ke lib. Unity masih belum menerapkannya dengan benar.
  5. Shader berat dengan argumen ekstra untuk gaya pendukung. Itu meningkatkan biaya render, karena kita harus merendernya secara realtime.
    Dan tentu saja kita harus men-cache-nya sebagai tekstur.

@eXponenta

  • Teks dapat dikelompokkan - meskipun tidak dengan hal-hal lain seperti grafik.

  • Implementasi Teks saat ini menyimpan cache setiap mesin terbang beberapa kali (jika sebuah huruf digunakan beberapa kali di beberapa PIXI.Teks). Memiliki satu geometri per mesin terbang lebih baik. Selain itu, Anda tidak perlu melakukan cache pada ukuran font yang berbeda.

  • Geometri tidak perlu dibuat ulang per say - jika huruf dalam teks berubah, Anda perlu mengambil lagi dari tabel geometri mesin terbang. Jika transformasi berubah, Anda hanya perlu mengubah satu seragam.

  • Kita dapat menggunakan perpustakaan untuk penguraian font. Konversi ke geometri adalah sepele.

  • Saya tidak tahu apa aturan penggabungan mesin terbang itu. Bisakah Anda menjelaskan?

  • Kiri-ke-kanan vs kanan-ke-kiri - jika Anda ingin membalik huruf, Anda bisa. Jika Anda ingin gambar cermin, maka atur scale.x=-1 internal.

  • Penataan gaya teks tidak akan menambahkan lebih banyak argumen ke shader. Ini akan mengubah geometri. Sekarang, menyimpan mesin terbang sebagai geometri membutuhkan memori _less_ daripada menyimpannya dalam tekstur.

  • File font yang diambil dari API harus di-cache di mesin pengguna.

kamu sangat naif:

  1. Itu harus batcher eksternal, karena mesin terbang memerlukan atribut tambahan, seperti jangkar bezier, nilai bayangan, jangkar gradien ..., atau semuanya harus dilewatkan sebagai seragam - selamat tinggal, batching.
  2. kanan-ke-kiri dan kiri-ke-kanan, dan campuran mereka adalah masalah yang sangat kompleks.
    Masalah yang dibuka di lib rendering PDF:
    https://github.com/asciidoctor/asciidoctor-pdf/issues/175
  3. Masalah Hindi (dan bahasa serupa)
    https://docs.microsoft.com/en-us/typography/opentype/spec/gsub

Kami tidak dapat menggunakan ketergantungan eksternal, karena akan menjadi masalah yang sama dengan isMobile atau resource-loader .
Inti harus bersih. Ketergantungan eksternal minimal.

@eXponenta

  • Tata letak campuran (gabungan ltr dan rtl) kurang diprioritaskan daripada kinerja tinggi. Anda selalu dapat mundur ke algoritme saat ini. Mirip dengan Devanagari. Fitur khusus seperti pemberhentian gradien juga membutuhkan fallback.

  • Batching dapat bekerja di sini karena akan lebih mudah tanpa tekstur apapun. Dapat membuat plugin seperti CanvasGraphicsRenderer .

Baik. kamu menang. Lakukan. Tapi di luar inti, maka kita akan melihat dan memutuskan apa yang harus kita lakukan kemudian.
Tetapi tanpa ketergantungan yang berat.

@eXponenta tolong berhenti bersikap bermusuhan. Kami sedang menjajaki pendekatan yang belum ada yang solid. Harap konstruktif dan tidak menggunakan penghinaan.

@eXponenta Apakah Anda yakin kami mendukung teks kanan-ke-kiri seperti sekarang?

Pendekatan lain yang kami pikirkan adalah membuat setiap mesin terbang menggunakan kanvas 2D (sama seperti sekarang) secara terpisah dan menyimpannya ke dalam atlas. Atlas dapat digunakan kembali secara global untuk semua instance PIXI.Text . Setiap kombinasi glyph + font-size + font-style akan di-cache secara terpisah.

Apa pendapat Anda tentang menerima itu menjadi inti?

Hei peeps, ini sangat menarik untuk mendengar pendekatan baru ini di atas meja. @eXponenta , bergema @bigtimebuddy ,

Pada teks, inilah 2 sen saya (pence?)..

Secara pribadi saya pikir pendekatan yang paling berharga adalah untuk mendapatkan kecepatan dan kinerja teks bitmap tetapi tanpa perlu benar-benar membuat font bitmap sebelumnya. Membangun tekstur bitmap dinamis jika Anda mau!

Font bitmap dinamis

pro

  • Alat untuk membuat font bitmap sangat sedikit dan jarang! Ingin sekali menghilangkan penghalang itu.
  • kita bisa membuat berbagai ukuran tekstur ukuran teks.
  • Bekerja dengan Kanvas
  • Performa karena setiap mesin terbang dapat dikelompokkan
  • banyak dari efek keren!
  • API hanya perlu sedikit penyesuaian:
const textStyle = new TextStyle({
    font:'comic sans',
    fill:'bright green'
});


const bitmapFont = new BitmapFont(textStyle);

kontra

  • semua kontra lain dari bitmap font bitmap saat ini: P
  • akankah memperbarui atlas tekstur secara dinamis menyebabkan perlambatan?

    • Meskipun ini akan stabil setelah beberapa saat, dan mungkin dapat di-cache di antara sesi?

    • Teks saat ini juga harus mengunggah tekstur setiap kali mengubah bingkai, pendekatan ini akan melakukannya lebih sedikit?

ide ide

  • Bisakah tekstur cache dihasilkan di penyimpanan lokal? untuk kunjungan berikutnya?
  • Hanya tambahkan karakter yang digunakan, jadi teksturnya sebesar yang dibutuhkan. Perbarui sambil berjalan
  • panggang dalam filter ke tekstur ini untuk efek ekstra keren (garis besar, bayangan, dll)
  • kita dapat mengeksplorasi pengurangan memori font bitmap dengan tidak membuat setiap mesin terbang menjadi sprite?

SDF
Dapatkah SDF menjadi perpanjangan dari pendekatan di atas? Seberapa rumitkah untuk menghasilkan tekstur itu secara dinamis? Apakah itu akan menjadi super janky? Apakah kita berbicara tentang meningkatkan basis kode dalam jumlah besar?

Kebanyakan orang tidak tahu apa itu sehingga idealnya harus disembunyikan. Jika kita perlu secara eksternal menghasilkan bidang SDF atau kode yang diperlukan untuk menghasilkan terlalu besar atau rumit maka ini akan lebih baik di rumah sebagai plugin pasti:

const textStyle = new TextStyle({
    font:'comic sans',
    fill:'bright green',
    sdf:true, <----- how sweet would this be, maybe rename to more user friendly like 'cleanEdges'
});

const sdfFont = new BitmapFont(textStyle);

Render kurva bezier yang tepat

Ini adalah pendekatan yang menarik pasti! Saya telah melihat ini di masa lalu dan memutuskan bahwa sakelar shader dimasukkan ke dalam loop rendering dan tessellation tambahan yang diperlukan akan memiliki overhead yang besar. @SukantPal , Anda lebih dekat dengan ide ini daripada saya sekarang, jadi saya ingin Anda menanggapi kekhawatiran saya!

Karena itu, mungkin perlu membangun prototipe yang dapat kita uji dan bash sedikit untuk memvalidasi pemikiran kita?

Waktu yang menyenangkan untuk teks :D

Dapatkah SDF menjadi perpanjangan dari pendekatan di atas? Seberapa rumitkah untuk menghasilkan tekstur itu secara dinamis? Apakah itu akan menjadi super janky? Apakah kita berbicara tentang meningkatkan basis kode dalam jumlah besar?

Pembuatan SDF mahal , dan ada waktu pengepakan (ketika kami menemukan font yang berbeda dikemas di atlass), tetapi dapat di-cache pada klien (seperti semua varian lainnya).
Ada kanvas (hehe) implementasinya:
https://github.com/mapbox/tiny-sdf
Tetapi kompilasi SDF tidak sepenuhnya benar (mesin terbang berubah saat menambah/mengurangi ukuran font)
Sepertinya berguna, tetapi untuk MSDF kita harus menjalankannya 3 kali (per saluran).

oh wow, itu sedikit kode! Terlihat matang untuk shader juga!

@GoodBoyDigital Paket tiny-sdf menghasilkan bidang jarak saluran tunggal. Itu tidak menghasilkan sudut tajam saat Anda menyimpan teks dalam ukuran font yang lebih kecil. Itu dapat dikurangi dengan melakukan caching pada ukuran font yang sama yang dirender.

Generasi SDF saluran tunggal seharusnya tidak terlalu buruk. Multi channel SDF lebih unggul kecuali terlalu rumit. Saya tidak mengerti bagaimana Chumskly menyandikan sudut.

Sekarang, semua yang kami pertimbangkan tidak akan mendukung campuran tata letak rtl dan Ltr (seperti yang ditunjukkan oleh @eXponenta dengan benar). Tapi saya tidak berpikir kami secara resmi mendukungnya sekarang juga.

Pendekatan yang tepat memiliki dua manfaat - ukuran cache kecil (Anda caching simpul tidak semua piksel), antialiasing bahkan ketika pengaturan "antialiasing" dimatikan (saya pikir teks diharapkan selalu antialias. Implementasi saat ini melakukannya dengan menggunakan kanvas 2D).

Adapun demo, apakah Anda melihat demo kurva Bézier kuadrat saya? https://codepen.io/sukantpal/pen/GRJawBg?editors=0010

——
Hal lain yang saya dan @bigtimebuddy diskusikan sebagai solusi paling sederhana adalah tetap menggunakan kanvas 2D dan menyimpan mesin terbang ke dalam tekstur. Mesin terbang dapat dirender sebagai segi empat. Atlas cache dapat digunakan kembali di antara teks. Tentu saja, ini berarti teks besar sedang di-cache pada ukuran yang sama dan karenanya penggunaan memori yang besar ketika banyak teks sedang dirender tetapi hanya sebagian darinya (seperti halaman saat ini dalam PDF) yang terlihat.

Bagus,

Ya, jangan khawatir tentang rtl atau ltr yang akan selalu tersedia melalui metode saat ini dan merupakan masalah, semua teknik rendering teks khusus perlu diselesaikan di kemudian hari.
Keputusan ini. idealnya harus fokus pada konsumsi memori dan kinerja runtime.

Demo Bezier itu keren, tapi saya rasa itu tidak cukup untuk memahami kerumitan sebenarnya yang mungkin tersembunyi jika kita membuat kalimat penuh.

Hal-hal yang saya tulis tentang bitmapfont dinamis di atas persis seperti yang Anda sebutkan tentang caching mesin terbang. Saya pikir itu pasti rute yang berguna untuk turun!

Kesimpulan:

Solusi kurva Bezier: Ini bisa menjadi rute yang baik, tetapi saya merasa ini membutuhkan R&D lebih lanjut untuk mengetahui bagaimana itu cocok dengan kasus penggunaan produksi nyata.

Bitmapfont Dinamis dari font normal: Ini harus kita jelajahi karena kita tahu ini akan memberikan kinerja yang baik sementara juga menjaga API tetap sederhana. Favoritku :D

SDF saluran tunggal Harganya tidak akan sebagus SDF multisaluran, tetapi demonya tampak cukup bagus bagi saya! Jika teks dapat diskalakan dengan baik dan kita dapat memiliki satu tekstur per font, maka saya pikir rute ini juga layak untuk diselidiki!

@GoodBoyDigital Saya pikir demo memiliki teks yang cukup bagus. Tetapi ada perbedaan yang terlihat jika Anda mencoba mencari detailnya:

Screen Shot 2020-04-06 at 1 34 29 PM

Screen Shot 2020-04-06 at 1 34 35 PM

Teks di atas tidak tajam - ujung-ujungnya bergoyang. Setiap kombinasi font+(~12-15px perbedaan ukuran font) mungkin perlu di-cache secara terpisah.

Saya baik-baik saja dengan menggunakan SDF jika goyangan itu tidak penting atau jika kita dapat menggunakan caching pada berbagai ukuran font.


Solusi paling sederhana juga baik untuk saya tbh!

Hai semua.

Saya sangat awam dalam segala hal tentang Pixi, tetapi saya adalah pengguna GDevelop yang menggunakan Pixi sebagai backendnya, dan saya telah menggali ini untuk sementara waktu untuk implementasi GDevelop dari PixiJS dan rendering teks. Ini benar-benar berdampak untuk game yang sedang saya kerjakan yang memiliki banyak teks. (Anda dapat melihat penelitian/contoh saya dalam masalah yang saya posting di GDevelop: https://github.com/4ian/GDevelop/issues/1449 )

Salah satu opsi yang saya temukan berfokus pada mengabaikan masalah penskalaan teks dan menghilangkannya sama sekali dengan selalu membiarkan skala teks pada 100%, tetapi menskalakan ukuran font teks saja? Ini adalah font agnostik, dan tampaknya berfungsi di semua ukuran.

Berikut adalah contoh kode yang dilakukan menggunakan Pixi: https://codepen.io/Tazy/pen/wJVExB
Saya menemukannya di utas ini: https://www.html5gamedevs.com/topic/29576-scalable-text-for-pixijs/

Saya sebenarnya memiliki karunia dalam masalah ini karena saya berharap seseorang dapat memodifikasi ekstensi Teks Pixi untuk GDevelop, tetapi (sebagai orang awam saya) saya tidak menyadari bahwa ini adalah masalah yang jauh lebih besar dengan Pixi itu sendiri.

Tidak tahu apakah ada masalah potensial dengan metode ini, tetapi tampaknya menghindari semua masalah kinerja sdf/msdf/etc.

@Silver-Streak Jika maksud Anda meningkatkan ukuran font dengan skala yang diterapkan pada objek tampilan teks, lalu bagaimana itu akan lebih baik dalam hal kinerja? Hal-hal SDF membantu kinerja karena Anda tidak merender ulang pada ukuran font yang lebih besar.

@Silver-Streak Tentu saja, proposal Anda akan meningkatkan _kualitas_ tetapi saya tidak melihat bagaimana itu akan meningkatkan kinerja.

@Silver-Streak Tentu saja, proposal Anda akan meningkatkan _kualitas_ tetapi saya tidak melihat bagaimana itu akan meningkatkan kinerja.

Kecuali saya salah paham, bukankah mengubah ukuran font menggunakan lebih sedikit sumber daya daripada menskalakan seluruh objek, atau memuat di perender lain? Sekali lagi, saya sangat awam dalam hal bagaimana penskalaan Pixi benar-benar bekerja, masuk akal bagi saya bahwa membiarkan font pada resolusi asli tetapi hanya mengubah ukuran teks akan lebih cepat daripada menskalakannya. Jika itu salah, mohon maaf atas gangguannya.

Penskalaan @Silver-Streak diimplementasikan sebagai transformasi. Anda memiliki matriks transformasi - dan mengubah skala dalam matriks itu adalah operasi sepele.

Sampai sekarang, teks dirender menggunakan Canvas 2D API menjadi kanvas. Kemudian disalin ke layar. Mengubah skala hanya akan mengubah koordinat layar tempat teks di kanvas dipetakan.

Ahh, itu masuk akal. Sangat disayangkan, meskipun untuk bersikap adil masalah saya lebih dengan rendering grafis font menjadi kabur setelah diskalakan, tapi saya pikir itu akan menjadi kinerja yang lebih baik juga.

Meskipun saya akan senang jika seseorang menerapkannya untuk memperbaiki masalah kualitas teks secara umum, saya benar-benar dapat memahami keinginan untuk meningkatkan kinerja juga.

Terima kasih telah membicarakannya dengan saya.

@Silver-Streak Tidak masalah. Namun, menerapkan teks yang mengutamakan kualitas seharusnya tidak sulit di WebGL. Beberapa aplikasi mengimplementasikan teks dengan membuat mesh sendiri. Anda dapat mengurai file font, membuat daftar simpul, dan mengujinya. Simpul tersebut dapat dirender melalui mesh.

Pada skala tinggi, ini dapat menyebabkan sedikit "tepian" - karena pada akhirnya, Anda membuat teks menjadi segitiga. Untuk kualitas yang lebih tinggi, Anda dapat menggunakan shader "kurva bezier persis" yang saya bicarakan di utas ini - itu akan membuat kurva sebagai kurva dan bukan segitiga.

Jika Anda memerlukan bantuan dengan kualitas teks, saya dapat membantu Anda :)

@SukantPal Saya jelas bukan kontributor untuk GDevelop, (Anda juga tidak menginginkan saya. Saya sebagian besar adalah Analis Sistem Bisnis/DevOps dalam hidup, bukan pengembang ) meskipun saya menyukai proyek itu dan aktif di komunitas . Saya juga tahu ada anggota komunitas lain yang ingin melihat solusi untuk kualitas teks yang diskalakan.

Namun, jika Anda ingin melihat masalah di pos, saya juga memiliki hadiah untuk itu di Bountysource juga terbuka untuk semua. Saya tidak ingin mengambil lebih banyak ruang di sini, karena jelas ada percakapan yang jauh lebih dalam terjadi di sekitar Pixi secara umum, dan saran saya tidak tepat seperti yang saya kira.

@Silver-Streak Saya mungkin melihatnya, karena saya tidak ada yang lebih baik untuk dilakukan di musim korona

Saya tahu ini adalah utas tertutup, tetapi saya yakin semua orang masih mencari cara terbaik untuk meningkatkan rendering teks. Saya memang memperhatikan bahwa seseorang memiliki implementasi msdf yang bekerja dengan Pixi v5. https://github.com/cjsjy123/pixi-msdf-text-v5 Pikir saya akan menyebutkannya kepada mereka yang tertarik.

Utas ini pasti harus dibuka kembali dan tetap hidup - atau setidaknya memiliki semacam pembaruan sesering mungkin, karena ini adalah salah satu masalah yang paling dicari.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

softshape picture softshape  ·  3Komentar

finscn picture finscn  ·  3Komentar

sntiagomoreno picture sntiagomoreno  ·  3Komentar

samueller picture samueller  ·  3Komentar

madroneropaulo picture madroneropaulo  ·  3Komentar