カスタム フィルタ(CSS シェーダー)の概要

カスタム フィルタ(以前は CSS シェーダーと呼ばれていました)を使用すると、DOM コンテンツで WebGL のシェーダーの機能を利用できます。現在の実装では、使用されるシェーダーは WebGL のシェーダーとほぼ同じであるため、3D の用語とグラフィック パイプラインの概要を理解する必要があります。

最近 LondonJS で行ったプレゼンテーションの録画版も添付しています。この動画では、理解しておく必要のある 3D の用語の概要、使用できるさまざまな変数の種類、カスタム フィルタの使い方について説明します。スライドもダウンロードして、デモを実際に試してみてください。

シェーダーの概要

以前に書いたシェーダーの概要では、シェーダーとは何か、WebGL の観点からシェーダーをどのように使用できるかについて詳しく説明しています。シェーダーを扱ったことがない場合は、カスタム フィルタのコンセプトと用語の多くが既存の WebGL シェーダーの用語に依存しているため、先に進む前に読んでおく必要があります。

では、カスタム フィルタを有効にして、作業を進めましょう。

カスタム フィルタの有効化

カスタム フィルタは、Chrome と Canary の両方、および Chrome for Android で利用できます。about:flags に移動して「CSS シェーダー」を検索し、有効にしてブラウザを再起動します。これで準備ができました。

構文

カスタム フィルタは、DOM 要素にすでに適用できるフィルタ(blursepia など)のセットに加えて、新しいフィルタを提供します。Eric Bidelman が、これらのテストに役立つ優れたプレイグラウンド ツールを作成しました。ぜひご確認ください。

カスタム フィルタを DOM 要素に適用するには、次の構文を使用します。

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

頂点シェーダーとフラグメント シェーダー、DOM 要素を分割する行と列の数、渡すユニフォームを宣言しています。

最後に、ブレンドモード(normal)と合成モード(source-atop)で、フラグメント シェーダーの周囲に mix() 関数を使用していることに注意してください。フラグメント シェーダー自体を見て、mix() 関数が必要な理由を確認しましょう。

ピクセル プッシュ

WebGL のシェーダーに精通している方には、カスタム フィルタの機能が少し異なるように見えるかもしれません。たとえば、フラグメント シェーダーがピクセルの塗りつぶしに使用するテクスチャは作成しません。フィルタが適用された DOM コンテンツは、自動的にテクスチャにマッピングされます。これは次の 2 つのことを意味します。

  1. セキュリティ上の理由から、DOM のテクスチャの個々のピクセルカラー値をクエリすることはできません
  2. Google は(少なくとも現在の実装では)最終的なピクセル色を自分で設定しません。つまり、gl_FragColor は使用できません。むしろ、DOM コンテンツをレンダリングすることを前提としており、css_ColorMatrixcss_MixColor を介してピクセルを間接的に操作できます。

つまり、フラグメント シェーダーの Hello World は次のようになります。

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

DOM コンテンツの各ピクセルは css_ColorMatrix で乗算されます。上記のケースでは、単位行列であるため何も行われず、RGBA 値は変更されません。たとえば、赤色の値のみを保持する場合は、次のように css_ColorMatrix を使用します。

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

4D(RGBA)ピクセル値に行列を掛けると、反対側から操作されたピクセル値が得られることがわかります。この場合は、緑と青のコンポーネントがゼロになります。

css_MixColor は主に、DOM コンテンツと混ぜ合わせるベースカラーとして使用されます。混合は、アート パッケージでよく使用されるオーバーレイ、スクリーン、カラードッジ、ハードライトなどのブレンド モードを使用して行われます。

これらの 2 つの変数でピクセルを操作する方法はたくさんあります。ブレンドモードと合成モードの相互作用を詳しく理解するには、フィルタ効果の仕様をご覧ください。

頂点の作成

WebGL では、メッシュの 3D ポイントの作成はすべてユーザーが行いますが、カスタム フィルタでは、必要な行と列の数を指定するだけで、ブラウザが DOM コンテンツを自動的に多数の三角形に分割します。

頂点の作成
行と列に分割された画像

これらの頂点は、操作のために頂点シェーダーに渡されます。つまり、必要に応じて 3D 空間内で移動できるようになります。すぐに、素晴らしい効果を作成できるようになります。

アコーディオン効果
アコーディオン効果によって歪められた画像

シェーダーによるアニメーション

シェーダーにアニメーションを導入すると、楽しく魅力的なシェーダーになります。そのためには、CSS で遷移(またはアニメーション)を使用して、均一な値を更新します。

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

上記のコードで注目すべき点は、遷移中に時間が 0 から 1 に緩和されることです。シェーダー内で、ユニフォーム time を宣言し、その現在の値を使用できます。

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

プレイする

カスタム フィルタは遊び心をくすぐる機能で、この機能なしでは作成できないような素晴らしいエフェクトを作成できます。まだ初期段階であり、状況は大きく変化していますが、これらの機能を追加すると、プロジェクトにエンターテイメントの要素が加わります。ぜひお試しください。

参考情報