Buat efek pensil di SVG

Gim saya Dragons Abound menciptakan peta dalam format grafik vektor SVG. Grafik vektor memiliki banyak fitur (misalnya, zoom lossless), yang nyaman untuk peta. Juga, grafik vektor baik untuk membuat garis yang jelas, seperti kontur tinta:


Di sisi lain, grafik vektor tidak pandai menciptakan tekstur dengan detail kecil yang tidak berulang. Dalam grafik vektor, setiap elemen yang direpresentasikan diwakili oleh deskripsi ukuran, bentuk, lokasi, warna, dll. Untuk menyajikan banyak detail kecil yang tidak berulang, perlu untuk menjelaskan sejumlah besar elemen. Misalnya, untuk garis pensil


puluhan ribu elemen berbeda akan dibutuhkan. Bahkan, setiap titik abu-abu dalam gambar akan diatur secara terpisah. Elemen-elemen lain, seperti gambar buram, bahkan lebih bermasalah.

Ini adalah batasan grafis vektor yang agak serius, jadi trik telah ditambahkan ke SVG yang memungkinkan Anda untuk secara efektif mereproduksi beberapa efek tekstur ini. Saya akan mengeksplorasi beberapa fitur SVG ini untuk membuat efek garis pensil. Tentu saja, ada banyak solusi yang lebih kompleks untuk menciptakan garis pensil. Seluruh artikel ilmiah telah ditulis tentang topik ini . Tetapi saya hanya berharap untuk membuat filter yang cukup sederhana yang memberikan hasil yang dapat diterima.

Seperti biasa, saya lebih suka meminjam atau memodifikasi filter yang dibuat oleh seseorang yang lebih berbakat daripada saya, tetapi dalam hal ini ada kekurangan filter pensil vektor yang dapat digunakan untuk inspirasi. (Musik peringatan yang tidak menyenangkan terdengar: mungkin ada alasan untuk ini.) Karena itu, pada kenyataannya, saya hanya bisa mengandalkan diri sendiri.

Sebelumnya, saya menulis tentang kemungkinan Dragons Abounduntuk membuat garis "tulisan tangan". Pada dasarnya, kemudian saya mempertimbangkan kemungkinan untuk menghindari garis lurus matematis dan membuat garis dengan sedikit penyimpangan yang terlihat lebih dekat dengan apa yang bisa ditarik oleh tangan seseorang. Di awal artikel, contoh ilustrasi gunung ditampilkan. Untuk membuat gaya ilustrasi tinta, ini sudah cukup, tetapi tidak cocok untuk membuat garis pensil, karena tidak memiliki tekstur pensil.

Jika Anda melihat garis pensil yang ditunjukkan di atas dan di bawah:


Anda akan melihat banyak fitur yang membedakan goresan pensil dari garis tinta (atau garis yang ditarik oleh komputer). Perbedaan yang paling penting adalah bahwa mereka memiliki tekstur yang dihasilkan dari cara pensil berinteraksi dengan kertas. Kertasnya kasar, dan pensil biasanya meninggalkan grafit di bagian gandum yang tinggi, sedangkan bagian yang rendah tetap putih. Pada kertas kasar, teksturnya lebih terlihat; menggambar karton begitu halus sehingga hampir tidak membuat tekstur. Kedua, ujung-ujung garis pensil agak kabur. Sekali lagi ini sebagian besar disebabkan oleh ketidak rataan kertas dan ujung pensil; ini mengarah pada fakta bahwa sepanjang tepi garis tetap memiliki jumlah grafit yang berbeda.

(Tentu saja, ada efek lain. Jejak pensil menutupi dirinya sendiri, sehingga menjadi lebih gelap di persimpangan goresan-goresan. Guratan itu sendiri bervariasi dalam tekanan dan ini dapat mengubah kegelapan goresan sepanjang panjangnya. Dalam posting ini, saya terutama akan fokus pada merekonstruksi tekstur kertas.)

Untuk Saya mulai dengan menyiapkan garis abu-abu sederhana:


Saya menggambar garis "tulisan tangan" dengan ketebalan 4, 2, dan 1 piksel. Sayangnya, efek SVG biasanya terlihat berbeda untuk garis dengan panjang yang berbeda, jadi saya ingin membandingkan efek pada ukuran yang berbeda.

Fungsi utama yang disediakan oleh SVG untuk menambahkan efek tekstur disebut filter . Filter diterapkan setelah memberikan efek vektor dan mengubah tampilannya. Filter konvensional dapat melakukan tindakan seperti mengubah warna objek, menambahkan noise, dll. Penyaring adalah topik yang agak membingungkan dengan sintaksis kompleks, jadi saya tidak akan memberikan tutorial lengkap tentang cara menggunakannya, tetapi saya akan menjelaskan dengan cukup detail sehingga jelas apa yang saya lakukan. Dan di akhir posting saya akan memberikan tautan ke Codepen dengan filter sehingga Anda bisa mencobanya sendiri.

Pertama, saya akan mencoba mengubah tepi garis agar tidak mulus, tetapi memiliki karakteristik penyimpangan pada kertas. Saya akan melakukan ini dengan memindahkan piksel garis. Elemen filter melakukan tugas ini disebut "feDisplacementMap"; itu bergerak setiap pixel berdasarkan nilai-nilai di gambar lain. Karena kami ingin setiap piksel bergerak secara acak tetapi seragam, kami perlu meneruskan derau ke feDisplacementMap untuk mengontrol pergerakan. Untungnya, SVG memiliki elemen filter lain yang disebut "feTurbulence" yang dirancang khusus untuk menciptakan kebisingan. Jadi kita bisa menggabungkan dua filter untuk memperkeras tepi garis.

Besarnya dan kekasaran garis dapat dikontrol oleh parameter dari peta perpindahan dan generasi kebisingan. Sayangnya, offset ditunjukkan dalam satuan absolut, tidak relatif terhadap ukuran garis. Saya memilih parameter, mencoba menemukan sesuatu yang sesuai dengan semua lebar garis, tetapi dengan peningkatan skala offset, Anda dapat melihat masalahnya:


Sekarang perpindahannya begitu hebat sehingga bisa menggerakkan seluruh garis, dan tidak hanya mengubah tepinya. Efek ini bahkan lebih terlihat pada garis tipis. Dalam contoh ini, garis dengan lebar 4 piksel pada dasarnya tampak seolah-olah ujungnya kasar, dan distorsi sudah terbukti dalam garis dengan ketebalan 2 piksel. Artinya, saya perlu memilih nilai yang tidak membuat distorsi dalam garis tipis.

Saat memperbesar dengan peningkatan standar dalam game, efeknya terlihat seperti ini (setelah memilih parameter untuk meningkatkan efek):


Pada skala ini, banyak tepi kasar menjadi bintik-bintik dan titik-titik. Ini bukan efek yang sangat tidak menyenangkan, dan agak mengingatkan pada garis pensil. (Namun, secara umum, filter SVG tampaknya memiliki masalah dengan penskalaan - dalam banyak kasus, ketika diperbesar, mereka terlihat bagus, tetapi mereka mengalami algoritme pengubahan ukuran yang buruk saat bergerak menjauh.)

Berikut adalah efeknya ketika menggambar gunung (efek pensil di sebelah kiri):


Tidak terlalu mengerikan, tetapi garis memiliki artefak yang tajam yang terlihat sedikit aneh. Dan ketika efeknya diterapkan pada garis tipis dan berjarak dekat, hasilnya tumpang tindih dan bergabung sebagai hasilnya:


Saya ulangi, ini tidak begitu mengerikan, dan bayangan pada gunung pensil sebagai hasilnya terlihat sangat mirip dengan yang digambar oleh pensil, jika Anda hanya membutuhkan efek seperti itu.

Solusi ini menambah kekasaran pada kontur goresan pensil, tetapi tidak mengubah warna seragam coretan. Tekstur juga ada di dalam goresan pensil nyata, karena grafit meninggalkan bercak di atas kertas secara tidak rata.

Untuk menambahkan tekstur ke bagian dalam goresan, saya menggunakan filter SVG dan kemudian menggabungkan derau dengan goresan:


Ketika diperbesar, Anda dapat melihat bahwa bagian dalam setiap goresan sekarang diisi dengan tekstur pseudo-grafit. Begini tampilannya pada skala normal:


Cukup bagus, terutama pada garis tebal. Begini tampilannya saat menggambar gunung:


Pada skala ini, semuanya tidak terlalu baik. Perhatikan bahwa filter ini juga mengurangi kegelapan garis; ini adalah hasil alami dari menambahkan white noise ke garis. Sampai batas tertentu, masalah ini dapat diatasi dengan meningkatkan kontras kebisingan, sehingga beberapa bagian dari garis kompensasi menjadi lebih gelap:


Tetapi karena warna garis sudah cukup gelap, ini sebagian besar menghancurkan efek "pensil". Karena itu, jika saya menggunakan ini, saya perlu memilih parameter untuk membuat keseimbangan yang menyenangkan.

Jelas, kedua solusi tersebut dapat digabungkan. Dengan peningkatan, hasilnya terlihat cukup bagus:


Dari garis pensil, kami mengharapkan tepi kasar dan tekstur internal. Pada skala standar, semuanya tidak begitu baik:


karena artefak yang tajam yang muncul pada skala ini.

Trik yang baik untuk meningkatkan tekstur ini adalah dengan menambahkan tekstur kertas ke latar belakang:


Sekarang mata merasakan seragam tekstur di seluruh gambar. Bahkan pada tingkat yang sangat implisit, ini membantu menipu mata dan meyakinkan bahwa tekstur garis disebabkan oleh interaksi dengan kertas.

Berikut adalah contoh penggunaan filter ini pada peta (dengan tekstur kertas):


Secara umum, semuanya tidak buruk, tetapi dengan studi rinci tampaknya di mana-mana hanya menambah kebisingan. Dengan peningkatan 200%, artefak menjadi lebih jelas:


Cara lain untuk membuat tepi kasar garis pensil adalah menggambar garis beberapa kali dengan penyimpangan yang sedikit berbeda dan mengurangi opacity. Di tengah garis, di mana beberapa versi berpotongan, kerapatan akan mendekati kerapatan garis asli; di tepi luar, di mana kadang-kadang hanya ada bagian dari garis, opacity akan lebih rendah, dan ujung-ujungnya akan kurang terbaca.

Secara umum, untuk mengimplementasikan solusi seperti itu menggunakan filter SVG, Anda perlu menggunakan feTurbulence dan feDisplacementMap bersama-sama untuk membuat versi garis yang terdistorsi. Namun, untuk melakukan ini beberapa kali dan menggabungkan semua garis di akhir, Anda memerlukan seperangkat primitif feBlend. Jika, misalnya, kami mencampur tiga salinan, kami perlu mengurangi opacity garis secara tepat. (Saya tidak begitu yakin bagaimana cara menghitung opacity yang sesuai, tetapi saya pikir itu bisa menjadi akar pangkat dari luminositas garis.)

Ini menciptakan efek (tiga baris dengan peningkatan):


Pendekatan ini memiliki beberapa kelemahan. Filter memiliki penyimpangan tetap, oleh karena itu mempengaruhi garis sempit lebih kuat, dan pada beberapa titik dapat dilihat bahwa garis piksel tunggal benar-benar dibagi. Kedua, ini adalah filter yang agak rumit yang menciptakan tiga penyimpangan terpisah dan menggabungkannya; bisa sangat lambat pada gambar yang kompleks seperti kartu Dragons Abound .

Begini tampilannya pada skala standar:


Menurut pendapat saya, ini tidak seperti garis pensil, tetapi lebih baik menghilangkan artefak yang tajam dari solusi sebelumnya.

Pendekatan ini dapat dikombinasikan dengan filter tekstur internal yang dijelaskan di atas dan menambahkan tekstur di dalam garis pensil, serta tekstur kertas:


Begini tampilannya setelah mendaftar ke pegunungan:


Filter ini cenderung mendistribusikan garis lebih kuat daripada filter lain, pada dasarnya membuatnya lebih tebal. Terkadang ia menghasilkan efek sketsa dengan beberapa baris, yang tidak terlalu buruk.

Berikut adalah contoh penggunaan filter ini di peta:


Ini mempertahankan kegelapan asli lebih baik daripada filter pertama, dan meskipun menurut saya itu tidak persis seperti pensil, efeknya cukup menyenangkan. Dengan peningkatan 200%:


Saat diperbesar, filter ini tidak memperoleh artefak tajam dari filter pertama. Efek memotong garis pada garis tipis (misalnya, seperti pada gambar hutan) mulai terlihat cukup buatan, tetapi garis yang lebih luas (gunung dan sungai) masih terlihat bagus. Namun, dalam garis hitam, seperti sungai, kebisingan internal hampir sepenuhnya hilang.

Saya memposting kedua filter ini pada Codepen sehingga Anda dapat mencobanya sendiri. Filter pertama di sini , yang kedua di sini . Saya sarankan untuk bereksperimen dengan mereka dan mencoba untuk memperbaikinya, dan jika Anda mendapatkan sesuatu yang lebih baik dari milik saya, maka beri tahu saya! Saya ingin memiliki filter pensil yang sangat bagus!

All Articles