Pengantar Filter Kustom (alias Shader CSS)

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

Saya telah menyertakan versi rekaman presentasi yang baru-baru ini saya sampaikan ke LondonJS. Dalam video ini, saya akan menjelaskan ringkasan terminologi 3D yang perlu Anda pahami, berbagai jenis variabel yang akan Anda temui, dan cara mulai menggunakan Filter Kustom sekarang. Anda juga harus mengambil slide agar dapat memainkan demo sendiri.

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, Anda harus membacanya sebelum melanjutkan, karena banyak konsep dan bahasa Filter Kustom bergantung pada terminologi shader WebGL yang ada.

Jadi, mari kita aktifkan Filter Kustom dan lanjutkan.

Mengaktifkan Filter Kustom

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

Sintaksis

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

Untuk menerapkan Filter Kustom ke elemen DOM, Anda menggunakan sintaksis 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)
}

Anda akan melihat dari sini bahwa kita mendeklarasikan shader vertex dan fragmen, jumlah baris dan kolom yang kita inginkan untuk dipecah menjadi elemen DOM, lalu seragam yang ingin kita teruskan.

Hal terakhir yang perlu ditunjukkan di sini adalah kita menggunakan fungsi mix() di sekitar shader fragmen dengan mode gabungan (normal), dan mode gabungan (source-atop). Mari kita lihat shader fragmen itu sendiri untuk melihat mengapa kita memerlukan fungsi mix().

Pendorong Piksel

Jika sudah memahami shader WebGL, Anda akan melihat bahwa di Filter Kustom, hal-halnya sedikit berbeda. Pertama, kita tidak membuat tekstur yang digunakan shader fragmen untuk mengisi piksel. Sebaliknya, konten DOM yang telah menerapkan filter akan dipetakan ke tekstur secara otomatis, dan hal ini berarti dua hal:

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

Artinya, Hello World shader fragmen kita akan 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 merupakan matriks identitas 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);

Anda dapat melihat bahwa saat Anda mengalikan nilai piksel 4D (RGBA) dengan matriks, Anda akan mendapatkan nilai piksel yang dimanipulasi dari sisi lain, dan dalam hal ini, nilai yang meniadakan komponen hijau dan biru.

css_MixColor terutama digunakan sebagai warna dasar yang ingin Anda gabungkan dengan konten DOM. Pencampuran dilakukan melalui mode campuran yang akan Anda kenal dari paket seni: overlay, layar, color dodge, hard light, dan sebagainya.

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

Pembuatan Vertex

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

Pembuatan vertex
Gambar yang dibagi menjadi baris dan kolom

Setiap vertex tersebut kemudian diteruskan ke vertex shader untuk dimanipulasi, dan itu berarti kita dapat mulai memindahkannya di ruang 3D sesuai kebutuhan. Tidak lama lagi Anda dapat membuat beberapa efek yang cukup luar biasa.

Efek akordeon
Gambar yang dibelokkan oleh efek akordeon

Menganimasikan dengan Shader

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

.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 melambat dari 0 ke 1 selama transisi. Di dalam shader, kita dapat mendeklarasikan time seragam dan menggunakan nilai 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;
}

Mulai Bermain!

Filter Kustom sangat menyenangkan untuk digunakan, dan efek luar biasa yang dapat Anda buat akan sulit (dan dalam beberapa kasus tidak mungkin) tanpanya. Ini masih awal, dan banyak hal yang berubah, tetapi menambahkannya akan menambah sedikit nuansa showbiz ke project Anda, jadi mengapa tidak mencobanya?

Referensi Tambahan