Giới thiệu về Bộ lọc tuỳ chỉnh (còn gọi là Chương trình đổ bóng CSS)

Bộ lọc tùy chỉnh hay CSS Shaders như thường được gọi, cho phép bạn sử dụng sức mạnh của chương trình đổ bóng của WebGL với nội dung DOM của bạn. Vì trong quá trình triển khai hiện tại, các chương trình đổ bóng được sử dụng gần như giống với các chương trình trong WebGL, bạn cần lùi lại một chút và hiểu một số thuật ngữ 3D cũng như một số quy trình xử lý đồ họa.

Tôi đã đính kèm một phiên bản được ghi lại của bản trình bày mà tôi mới gửi cho LondonJS. Trong video này, tôi đã trình bày tổng quan về thuật ngữ 3D mà bạn cần hiểu rõ, bạn sẽ gặp những loại biến nào và cách bắt đầu sử dụng Bộ lọc tuỳ chỉnh ngay hôm nay. Bạn cũng nên cầm các trang trình bày để có thể tự chơi theo bản minh hoạ.

Giới thiệu về Chương trình đổ bóng

Trước đây, tôi đã viết phần giới thiệu về chương trình đổ bóng nhằm cung cấp cho bạn thông tin phân tích chi tiết về chương trình đổ bóng và cách bạn có thể sử dụng chúng từ quan điểm WebGL. Nếu bạn chưa bao giờ xử lý chương trình đổ bóng, thì bạn cần phải đọc trước khi thực hiện thêm, bởi vì nhiều khái niệm và bản lề ngôn ngữ của Bộ lọc tuỳ chỉnh cũng như bản lề ngôn ngữ của thuật ngữ hiện có trong chương trình đổ bóng WebGL.

Vậy nên, hãy bật Bộ lọc tuỳ chỉnh và làm quen với sản phẩm!

Bật bộ lọc tuỳ chỉnh

Bộ lọc tuỳ chỉnh có trong cả Chrome và Canary, cũng như Chrome dành cho Android. Bạn chỉ cần truy cập vào about:flags rồi tìm "CSS Shaders", bật CSS Shaders rồi khởi động lại trình duyệt. Giờ thì bạn đã sẵn sàng!

Cú pháp

Bộ lọc tuỳ chỉnh mở rộng tập hợp các bộ lọc mà bạn có thể áp dụng (như blur hoặc sepia) cho các phần tử DOM. Eric Bidelman đã viết một công cụ sân chơi tuyệt vời dành cho những trò chơi đó và bạn nên tham khảo.

Để áp dụng Bộ lọc tuỳ chỉnh cho một phần tử DOM, bạn sử dụng cú pháp sau:

.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)
}

Như vậy, bạn sẽ thấy rằng chúng ta khai báo chương trình đổ bóng đỉnh và phân đoạn, số hàng và cột mà chúng ta muốn chia nhỏ thành phần DOM, sau đó phân chia bất kỳ đồng nhất nào mà chúng ta muốn chuyển qua.

Điều cuối cùng cần lưu ý ở đây là chúng ta sử dụng hàm mix() xung quanh chương trình đổ bóng mảnh bằng chế độ kết hợp (normal) và chế độ kết hợp (source-atop). Hãy xem chính chương trình đổ bóng này để biết lý do tại sao chúng ta cần hàm mix().

Đẩy pixel

Nếu đã quen thuộc với chương trình đổ bóng của WebGL, bạn sẽ nhận thấy rằng trong Bộ lọc tùy chỉnh, mọi thứ hơi khác một chút. Đối với một chương trình đổ bóng, chúng ta không tạo(các) hoạ tiết mà chương trình đổ bóng mảnh sử dụng để điền vào các pixel. Thay vào đó, nội dung DOM đã áp dụng bộ lọc sẽ tự động được ánh xạ đến một kết cấu, điều đó có nghĩa là:

  1. Vì lý do bảo mật, chúng tôi không thể truy vấn các giá trị màu sắc theo từng điểm ảnh của hoạ tiết DOM
  2. Chúng tôi không (ít nhất là trong các quy trình triển khai hiện tại) tự đặt màu pixel cuối cùng, tức là gl_FragColor không tuân theo giới hạn. Thay vào đó, hệ thống giả định rằng bạn sẽ muốn hiển thị nội dung DOM và việc bạn cần làm là điều khiển gián tiếp các pixel thông qua css_ColorMatrixcss_MixColor.

Tức là chương trình đổ bóng mảnh Hello World sẽ có dạng như sau:

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?
}

Mỗi pixel của nội dung DOM được nhân với css_ColorMatrix. Trong trường hợp trên, mỗi pixel không có tác dụng gì như ma trận nhận dạng và không thay đổi giá trị RGBA nào. Giả sử nếu muốn, chúng ta chỉ cần giữ lại các giá trị màu đỏ mà chúng ta sẽ sử dụng css_ColorMatrix như sau:

// 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);

Hy vọng rằng bạn có thể thấy rằng khi bạn nhân giá trị pixel 4D (RGBA) với ma trận mà bạn nhận được giá trị pixel bị bóp méo ở phía bên kia, và trong trường hợp này, một giá trị sẽ loại bỏ các thành phần màu xanh lục và màu xanh lam.

css_MixColor chủ yếu được dùng làm màu cơ bản mà bạn muốn kết hợp với nội dung DOM. Việc kết hợp được thực hiện qua các chế độ kết hợp mà bạn sẽ quen thuộc trong các gói hình minh hoạ: lớp phủ, màn hình, tính năng tránh màu, ánh sáng cứng, v.v.

Có rất nhiều cách để 2 biến này có thể thao tác các pixel. Bạn nên xem thông số kỹ thuật Hiệu ứng bộ lọc để xử lý tốt hơn về cách chế độ kết hợp và kết hợp tương tác với nhau.

Tạo Vertex

Trong WebGL, chúng tôi chịu hoàn toàn trách nhiệm tạo điểm 3D cho lưới của mình, nhưng trong Bộ lọc tùy chỉnh, bạn chỉ cần chỉ định số hàng và cột mà bạn muốn, sau đó trình duyệt sẽ tự động chia nội dung DOM của bạn thành nhiều hình tam giác:

Tạo Vertex
Một hình ảnh được chia nhỏ thành hàng và cột

Sau đó, mỗi đỉnh trong số các đỉnh đó được chuyển tới chương trình đổ bóng đỉnh để thao tác, tức là chúng ta có thể bắt đầu di chuyển chúng trong không gian 3D khi cần. Chẳng mấy chốc bạn sẽ có thể tạo ra một số hiệu ứng khá tuyệt vời!

Hiệu ứng đàn phong cầm
Một hình ảnh bị làm méo do hiệu ứng phong cầm

Tạo ảnh động bằng chương trình đổ bóng

Việc đưa ảnh động vào chương trình đổ bóng là điều khiến chúng trở nên thú vị và hấp dẫn. Để làm điều đó, bạn chỉ cần sử dụng hiệu ứng chuyển đổi (hoặc ảnh động) trong CSS để cập nhật các giá trị đồng nhất:

.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);
}

Vì vậy, điều cần lưu ý trong mã ở trên là thời gian sẽ giảm dần từ 0 sang 1 trong quá trình chuyển đổi. Bên trong chương trình đổ bóng, chúng ta có thể khai báo time đồng nhất và sử dụng bất kỳ giá trị hiện tại nào của chương trình đổ bóng đó:

    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;
}

Bắt đầu chơi!

Bộ lọc tuỳ chỉnh rất thú vị khi sử dụng, nhưng nếu không có những hiệu ứng tuyệt vời này thì sẽ khó tạo ra được (và trong một số trường hợp không thể tạo ra được). Vẫn chỉ mới bắt đầu và mọi thứ đang thay đổi khá nhiều, nhưng việc thêm họ vào các dự án của bạn sẽ bổ sung một chút tính giải trí cho dự án, vậy tại sao bạn không thử?

Nguồn thông tin khác