CSS Shaders はじめの 7歩目、色の塗りつぶしと乗算

Posted :

GraphicalWeb Advent Calendar 2012 の 12日目の記事です。

今回は、CSS Shaders における fragment shader の基本として、塗りつぶしと乗算についてを見ていきます。せっかくなので、前回作成したサンプルの fragment shader を編集していきます。

前回作成したサンプルのおさらい

HTML と CSS

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSS Shaders!</title>
<style>
.sample {
    width:500px;
    background: url( bg.png );
    -webkit-filter: custom(
        url( shader.vs ) mix( url( shader.fs ) ),
        32 32,
        u_transform perspective( 1000 ) rotateX( 45deg )
    );
}
</style>
</head>
<body>

<div class="sample">
    <p>CSS Shader!! シィーエスエス シェーダー!! </p>
    <img src="nyantocat.gif" alt="">
    <p>the Nyantocat by Cameron McEfee</p>
</div>

</body>
</html>

vertex shader

precision mediump float;

attribute vec4 a_position;
attribute vec2 a_meshCoord;

uniform mat4 u_projectionMatrix;
uniform mat4 u_transform;

void main() {
    float z = sin( a_meshCoord.x * 3.1415) * 100.0;
    vec4 pos = vec4( a_position.xy, z, a_position.w );

    gl_Position = u_projectionMatrix * u_transform * pos;
}

前回までは fragment shader として読み込んでいる shader.fs の内容は空でした。今回は新たにこの中身を書いていきます。

ここまでの状態の demo(2012年 12月現在では CSS Shader を有効にした Chrome 25以降である必要があります。)

fragment shader を適用する

fragment shader を mix() を使わずに、そのままの状態で適用してみましょう。CSS のコードでは、これまで mix( url( shader.fs ) ) としていた部分を url( shader.fs ) とします。

.sample {
    width:500px;
    background: url( bg.png );
    -webkit-filter: custom(
        url( shader.vs ) url( shader.fs ),
        32 32,
        u_transform perspective( 1000 ) rotateX( 45deg )
    );
}

そして、shader.fs の内容を次のように用意します。

precision mediump float;

void main() {
    gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );
}

fragment shader では、main 関数で最終的に gl_FragColor に代入された色が処理中のピクセルの色となります。ここでは gl_FragColorvec4( 1.0, 0.0, 0.0, 1.0 ) を代入しています。すると全ピクセルは赤で塗りつぶされることになります。

gl_FragColorvec4 型を座標としてではなく vec4( 赤, 緑, 青, 透明度 ) のように色として利用しているわけです。

ここまでの状態の demo

色を乗算する

塗りつぶしてしまってはせっかくのコンテンツが見えなくなってしまいます。そこで乗算を利用します。

CSS 側では fragment shader の指定を url( shader.fs ) から mix( url( shader.fs ) multiply ) に変更します。

.sample {
    width:500px;
    background: url( bg.png );
    -webkit-filter: custom(
        url( shader.vs ) mix( url( shader.fs ) multiply ),
        32 32,
        u_transform perspective( 1000 ) rotateX( 45deg )
    );
}

fragment shader では色が gl_FragColor ではなく、css_MixColor に代入されるように変更します。

precision mediump float;

void main() {
  css_MixColor = vec4( 1.0, 0.0, 0.0, 1.0 );
}

すると、コンテンツに対して、任意の色が乗算され表示されます。

ここまでの状態の demo(2012年 12月現在では CSS Shader を有効にした Chrome 25以降である必要があります。)