Pengantar Filter Kustom (alias Shader CSS)

Filter Kustom, atau Shader CSS, seperti yang biasa disebut, memungkinkan Anda menggunakan kecanggihan shader WebGL dengan konten DOM Anda. Karena dalam implementasi saat ini, shader yang digunakan hampir sama dengan yang ada di WebGL, sehingga Anda perlu mundur sejenak dan memahami beberapa terminologi 3D dan sedikit pipeline grafis.

Saya menyertakan versi rekaman presentasi yang baru-baru ini saya sampaikan ke LondonJS. Dalam video ini, saya menjelaskan ikhtisar terminologi 3D yang perlu Anda pahami, berbagai jenis variabel yang akan Anda temui, dan bagaimana Anda dapat mulai bermain dengan Filter Kustom sekarang. Anda juga harus mengambil slide agar Anda dapat bermain sendiri demonya.

Pengantar Shader

Sebelumnya saya telah menulis pengantar shader yang akan memberi Anda perincian yang baik tentang apa itu shader dan cara menggunakannya dari sudut pandang WebGL. Jika Anda belum pernah menangani shader, itu adalah bacaan wajib sebelum Anda melangkah lebih jauh, karena banyak konsep Filter Kustom dan bahasa bergantung pada terminologi shader WebGL yang ada.

Jadi, mari kita aktifkan Filter Kustom lalu mulai nyala.

Mengaktifkan Filter Kustom

Filter Kustom tersedia di Chrome dan Canary, serta Chrome untuk Android. Cukup buka about:flags dan cari "CSS Shaders", aktifkan, lalu mulai ulang browser. Sekarang Anda siap untuk memulai!

Sintaksis

Filter Kustom memperluas kumpulan filter yang sudah dapat Anda terapkan, seperti blur atau sepia, ke elemen DOM. Eric Bidelman menulis alat bermain yang bagus untuk hal-hal tersebut, yang harus Anda lihat.

Untuk menerapkan Filter Khusus ke elemen DOM, Anda menggunakan sintaks berikut:

.customShader {
    -webkit-filter:

    custom(
        url(vertexshader.vert)
        mix(url(fragment.frag) normal source-atop),

    /* Row, columns - the vertices are made automatically */
    4 5,

    /* We set uniforms; we can't set attributes */
    time 0)
}

Dari sini Anda akan melihat bahwa kita mendeklarasikan shader verteks dan fragmen, jumlah baris dan kolom yang kita inginkan untuk memerinci elemen DOM, lalu semua uniform yang ingin diteruskan.

Hal terakhir yang perlu diperhatikan di sini adalah kita menggunakan fungsi mix() di sekitar shader fragmen dengan mode campuran (normal) dan mode gabungan (source-atop). Mari kita lihat shader fragmen itu sendiri untuk mengetahui alasan kita bahkan memerlukan fungsi mix().

Pengiriman Pixel

Jika sudah terbiasa dengan shader WebGL, Anda akan melihat bahwa ada sedikit perbedaan di Filter Kustom. Pertama, kita tidak membuat tekstur yang digunakan shader fragmen untuk mengisi piksel. Sebaliknya, konten DOM yang menerapkan filter akan otomatis dipetakan ke tekstur, dan itu berarti dua hal:

  1. Untuk alasan keamanan, kita tidak dapat membuat kueri nilai warna piksel individual dari tekstur DOM
  2. Kita tidak (setidaknya dalam implementasi saat ini) menetapkan sendiri warna piksel akhir, yaitu gl_FragColor dilarang. Sebaliknya, Anda dianggap ingin merender konten DOM, dan yang harus Anda lakukan adalah memanipulasi pikselnya secara tidak langsung melalui css_ColorMatrix dan css_MixColor.

Artinya, Hello World of fragment shader terlihat seperti ini:

void main() {
    css_ColorMatrix = mat4(1.0, 0.0, 0.0, 0.0,
                            0.0, 1.0, 0.0, 0.0,
                            0.0, 0.0, 1.0, 0.0,
                            0.0, 0.0, 0.0, 1.0);

    css_MixColor = vec4(0.0, 0.0, 0.0, 0.0);

    // umm, where did gl_FragColor go?
}

Setiap piksel konten DOM dikalikan dengan css_ColorMatrix, yang dalam kasus di atas tidak melakukan apa pun karena matriks identitasnya dan tidak mengubah nilai RGBA. Jika kita ingin, misalnya, hanya mempertahankan nilai merah, kita akan menggunakan css_ColorMatrix seperti ini:

// keep only red and alpha
css_ColorMatrix = mat4(1.0, 0.0, 0.0, 0.0,
                        0.0, 0.0, 0.0, 0.0,
                        0.0, 0.0, 0.0, 0.0,
                        0.0, 0.0, 0.0, 1.0);

Mudah-mudahan Anda dapat melihatnya saat mengalikan nilai piksel 4D (RGBA) dengan matriks, bahwa Anda mendapatkan nilai piksel yang dimanipulasi dari sisi lain, dan dalam hal ini nilai piksel yang nol komponen hijau dan biru.

css_MixColor terutama digunakan sebagai warna dasar yang ingin Anda campur dengan konten DOM Anda. Pencampuran dilakukan melalui mode campuran yang sudah terbiasa dengan paket seni: overlay, layar, penghindar warna, cahaya terang, dan sebagainya.

Ada banyak cara agar kedua variabel ini dapat memanipulasi piksel. Anda harus melihat spesifikasi Efek Filter untuk mendapatkan pemahaman yang lebih baik tentang cara mode campuran dan gabungan berinteraksi.

Pembuatan Vertex

Di WebGL, kami bertanggung jawab penuh atas pembuatan titik 3D mesh, namun di Filter Kustom, Anda hanya perlu menentukan jumlah baris dan kolom yang diinginkan, dan browser akan secara otomatis memecah konten DOM Anda menjadi sekumpulan segitiga:

Pembuatan vertex
Gambar yang dibagi menjadi baris dan kolom

Setiap verteks tersebut kemudian diteruskan ke shader verteks untuk manipulasi, dan itu berarti kita dapat mulai memindahkannya dalam ruang 3D sesuai kebutuhan. Tidak lama kemudian Anda dapat membuat beberapa efek yang sangat menakjubkan!

Efek akordeon
Gambar yang dilengkungkan oleh efek akordeon

Menganimasikan dengan Shader

Membawa animasi ke shader Anda adalah hal yang membuatnya menyenangkan dan menarik. Untuk melakukannya, cukup gunakan transisi (atau animasi) di CSS Anda untuk memperbarui nilai uniform:

.shader {
    /* transition on the filter property */
    -webkit-transition: -webkit-filter 2500ms ease-out;

    -webkit-filter: custom(
    url(vshader.vert)
    mix(url(fshader.frag) normal source-atop),
    1 1,
    time 0);
}

    .shader:hover {
    -webkit-filter: custom(
    url(vshader.vert)
    mix(url(fshader.frag) normal source-atop),
    1 1,
    time 1);
}

Jadi, hal yang perlu diperhatikan dalam kode di atas adalah waktu akan berkurang dari 0 menjadi 1 selama transisi. Di dalam shader, kita dapat mendeklarasikan time uniform dan menggunakan apa pun nilainya saat ini:

    uniform float time;

uniform mat4 u_projectionMatrix;
attribute vec4 a_position;

void main() {
    // copy a_position to position - attributes are read only!
    vec4 position = a_position;

    // use our time uniform from the CSS declaration
    position.x += time;

    gl_Position = u_projectionMatrix * position;
}

Ayo Bermain!

Filter Kustom sangat menyenangkan untuk digunakan, dan efek menakjubkan yang dapat Anda buat akan sulit (dan dalam beberapa kasus, tidak mungkin) tanpa filter tersebut. Ini masih terlalu awal, dan ada banyak hal yang berubah, tetapi menambahkannya akan menambah sedikit showbiz ke proyek Anda, jadi mengapa tidak mencobanya?

Referensi Tambahan