Troika: Ide cepat untuk meningkatkan antialiasing teks

Dibuat pada 17 Jun 2021  ·  7Komentar  ·  Sumber: protectwise/troika

Saya tidak yakin apakah Anda telah memperbarui kode antialiasing baru-baru ini, karena saya menggunakan versi yang lebih lama, tetapi setelah menemukan cara yang bagus untuk melakukan antialiasing lingkaran yang digambar shader, saya ingin mencobanya pada teks Anda juga , karena teksnya berbasis SDF, dan antialiasing lingkaran juga berbasis jarak.

Dalam versi Troika saya saat ini, Anda melakukan return length(fwidth(vTroikaGlyphUV * vTroikaGlyphDimensions)) * 0.5; untuk jarak aa. Ini memiliki artifak bahwa saat melihat pada suatu sudut, tepi paling kiri dan paling kanan mendapatkan keburaman yang agak terlihat:
image

Saya mengubahnya menjadi skalar; jaraknya, seperti dalam kode lingkaran saya: return fwidth(distance) * 0.5; Dengan jarak yang masuk dari troikaGetFragDistValue seperti ini: float distance = troikaGetFragDistValue(); float aaDist = troikaGetAADist(distance);
Melakukannya dengan cara ini saya tidak mendapatkan artefak yang kabur:
image

Faktor 0.5 dapat ditingkatkan untuk antialiasing yang lebih lancar. Misal 0.8 :
image

Saya pikir mungkin Anda tidak mengetahui metode ini seperti saya, jadi saya pikir saya akan membagikannya. "Implementasi" saya memang memiliki beberapa artefak aneh (lihat di bawah), dan mungkin ini sebabnya Anda memilih metode lain. Juga, saya tidak begitu yakin bagaimana Anda menggunakan variabel aaDist dalam kode shader, jadi Anda mungkin lebih siap dalam mengimplementasikan ini. Mungkin ada beberapa kode yang harus diubah atau dihapus karena perubahan ini misalnya, yang dapat meningkatkan "implementasi" saya lebih lanjut.

image

Saya menemukan metode melakukannya di posting bgolus di sini: https://forum.unity.com/threads/antialiasing-circle-shader.432119/ di mana ada beberapa info lebih lanjut. Dia juga mengatakan bahwa Anda dapat melakukan misalnya length(vec2(dFdx(distance), dFdy(distance))) alih-alih fwidth(distance) untuk presisi yang lebih besar, meskipun saya tidak yakin apakah ini dapat diabaikan atau tidak.

Semua 7 komentar

Terima kasih untuk sarannya! Saya pasti akan melihat ini, karena saya telah memperhatikan tepi buram pada sudut miring juga dan ingin menghilangkannya.

Secara teoritis saya pikir perubahan distance dan perubahan vTroikaGlyphUV * vTroikaGlyphDimensions harus setara karena keduanya mewakili jarak dalam unit ruang font, tetapi pasti ada beberapa perbedaan halus di sana yang saya miliki diabaikan. Jika saya dapat menghindari artefak yang Anda tunjukkan, maka saya akan dengan senang hati mengintegrasikan perubahan Anda. :)

Besar! Perubahannya sesederhana satu baris itu (dan meneruskan argumen jarak itu untuk mengakomodasinya). Jika Anda masih menginginkan kode mentah, saya dapat mengirimkannya ketika saya bekerja besok.

Secara teoritis saya pikir baik perubahan jarak dan perubahan vTroikaGlyphUV * vTroikaGlyphDimensions harus setara karena keduanya mewakili jarak dalam unit font-space

Saya tidak begitu mengerti bagaimana turunannya akan sama. distance saya kira adalah jarak SDF, tetapi yang lainnya adalah posisi uv yang diskalakan. Saya belum melihat kodenya dan bagaimana perbandingannya, tetapi rasanya turunannya harus berbeda. Sejauh yang saya tahu fwidth hanya mengambil perbedaan dari nilai input spesifik yang diteruskan sebagai argumen dengan nilai input spesifik yang sama di fragmen tetangga, yang dimungkinkan karena fragmen tetangga dieksekusi pada waktu yang sama secara paralel. Saya menjalankan tes sebelumnya hari ini dengan gl_FragColor.rgb = vec3(fwidth(gl_FragColor.x + gl_FragColor.g + gl_FragColor.b)); untuk melihat apakah itu membuat tepi seperti pada deteksi tepi/filter sobel, untuk mencoba mengkonfirmasi fakta itu sedikit, dan ternyata berhasil.

Terima kasih atas diskusinya, hal ini terkadang membuat otak saya rusak. ;)

Ketika saya mengatakan mereka "setara", maksud saya keduanya mewakili jarak dalam satuan yang sama, tetapi Anda benar, keduanya tidak persis sama.

Mencadangkan, yang kita inginkan di sini adalah tingkat _potensial_ perubahan antar fragmen. Menggunakan perubahan dalam variabel distance seperti yang Anda sarankan akan sering akurat untuk itu, tetapi dalam beberapa kasus itu akan sangat tidak akurat. Ini karena SDF dari mana nilai tersebut dijadikan sampel adalah _non-uniform_; itu melengkung dan mengubah arah perubahannya melintasi mesin terbang. Oleh karena itu turunan dari distance antara fragmen tetangga bisa menjadi terlalu kecil, bahkan nol, seperti di mana bidang jarak beralih dari naik ke turun di tengah antara jalur mesin terbang, atau terlalu besar, seperti saat teks ditampilkan pada ukuran kecil dan kisi fragmen melapisi SDF di lokasi yang tidak terduga. Saya menduga itu menjelaskan setidaknya beberapa artefak yang Anda lihat.

Jadi bagaimana kita bisa menentukan tingkat perubahan _potential_ tanpa menggunakan distance ? Nah, "posisi uv skala" seperti yang Anda sebut pada dasarnya adalah koordinat x/y dalam persegi mesin terbang, menggunakan unit yang sama dengan distance . Turunan dari x/y itu memberi kita tingkat perjalanan potensial antara fragmen. Secara keseluruhan itu memberikan hasil yang lebih baik daripada menggunakan distance , karena didasarkan pada tingkat perubahan _uniform_ di mesin terbang, dan oleh karena itu kami tidak mendapatkan artefak dan lebih akurat pada ukuran kecil.

Tapi, seperti yang Anda lihat, di mana ia rusak berada pada sudut miring; dalam kasus tersebut laju perubahan potensial x/y dalam vertikal jauh berbeda dari pada horizontal. Jadi kami akhirnya menggunakan satu nilai untuk tingkat potensi perubahan yang terlalu besar di satu arah dan terlalu kecil di arah lain, memberikan garis buram dan/atau terputus-putus tergantung pada arah perubahan SDF yang sebenarnya pada fragmen itu.

Jadi ya, pasti ada ruang untuk perbaikan dalam kasus miring, tetapi hanya menggunakan turunan dari distance saja tidak cukup. Saya terbuka untuk ide-ide untuk meningkatkan ini tentu saja. Satu kemungkinan adalah mencoba mendeteksi skenario (ukuran teks besar pada sudut miring, dekat dengan jalur) dan menggunakan turunan distance hanya dalam satu kasus itu.

Ya, hal ini membingungkan untuk dipikirkan, haha. Saya bisa melihat medan jarak kurang mulus, ya.

Piksel glitchy itu mungkin hanya karena fragmen di luar sana memiliki beberapa nilai jarak yang aneh.

Ini tidak terlalu berombak dari jauh, tetapi Anda pasti dapat melihat UV menjadi lebih baik. Mungkin interpolasi antara variabel jarak dan UV yang bergantung pada jarak kamera akan bekerja dengan baik; seperti dalam memilih lebih banyak fwidth (jarak) saat dekat, dan lebih banyak fwidth (uv) saat jauh.

Sebagai perbandingan (tidak menangkap keduanya pada posisi dan orientasi kamera yang sama persis, tapi saya pikir itu menunjukkan perbedaan dengan baik):
Jarak (faktor 0,8):
image
UV:
image

Saya perhatikan bahwa modifikasi ini secara signifikan meningkatkan hasil untuk transformasi teks khusus. Berikut adalah beberapa teks, dimodifikasi mengikuti kurva menggunakan createDerivedMaterial ( lihat teknik ini ). Ini menggunakan shader troika-tiga teks saat ini:

image

Ini adalah tangkapan layar yang sama, tetapi dengan modifikasi @asbjornlystrup menjadi troikaGetAADist :

image

Dalam bidikan kedua, Anda dapat melihat "HEBAT!" agak lebih renyah.

Secara anekdot: Saya juga menemukan bahwa mengutak-atik konstanta menjadi 0,25 (dari 0,5) juga menghasilkan tepi tajam yang bagus:

return length(fwidth(vTroikaGlyphUV * vTroikaGlyphDimensions)) * 0.25;

Terima kasih @canadaduane , saya pasti bisa melihat peningkatan di bagian yang diregangkan. Saya juga dapat melihat artefak jelek yang muncul di antara huruf L di HELLO, yang pasti harus kita ketahui sebelum mengadopsi perubahan ini.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

arpu picture arpu  ·  43Komentar

Ocelyn picture Ocelyn  ·  13Komentar

natarius picture natarius  ·  14Komentar

stephencorwin picture stephencorwin  ·  39Komentar

lojjic picture lojjic  ·  11Komentar