CSS Shaders はじめの 4歩目、簡単な変形 1

Posted :

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

この記事では、前回の記事サンプルに少し手を加え、簡単な変形を GLSL 内で行います。

前回のおさらい

次の HTML と vertex 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
    );
}
</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>

shader.vs

precision mediump float;

attribute vec4 a_position;
uniform mat4 u_projectionMatrix;

void main() {
    gl_Position = u_projectionMatrix * a_position;
}

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

今回は上記のコードに手を加え、vertex shader 内に、変換行列 (transform matrix) を用意し、要素を移動や回転をしてみます。

GLSL に登場する型

さて、コードを紹介する前に、今回登場する型についてすこし知っておきましょう。GLSL には JavaScript と違ってたくさんの型があります。

変数の種類

attribute|Shader に送られてくる頂点毎に内容が異なる変数
uniform|Shader に送られてくる一定の変数
const|定数

変数の型

float|小数点数
vec4|4成分のベクトル (4つの float の組み)
mat4|4x4 の行列 (16この float の組み)

移動する

さっそく、vertex shader に手を加え、移動をさせてみましょう。移動や回転などを行う方法の一つに、変換行列を利用する方法があります。ただし、次回もう少し簡単な方法を紹介します。今回の記事は軽く読み流しておけばいいでしょう。

移動するための変換行列はわかりやすいです。下に示す行列の Tx, Ty, Tz を移動したい距離に置き換えるだけです。




100Tx


010Ty


001Tz


0001


ただし、WebGL の場合は、行と列の順番が入れ替わるため、実際のコードでは以下のに当てはめることになります。

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,
     Tx,  Ty,  Tz, 1.0

);

X 方向に 0.5 移動させるには、次の行列を mat4 変数として用意して乗算します。

mat4 translate = 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.5, 0.0, 0.0, 1.0
);

vertex shader に反映してみます。

precision mediump float;

attribute vec4 a_position;
uniform mat4 u_projectionMatrix;

void main() {
    mat4 translate = 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.5, 0.0, 0.0, 1.0
    );
    gl_Position = u_projectionMatrix * translate * a_position;
}

結果は次のようになります。CSS Shader による効果で X 方向に 0.5 動いたことがわかります。

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

回転する

回転は移動より少し複雑な行列が必要です。ここでは z 軸に対して回転する例をみてみましょう。z 軸に対して任意の角度分回転するには次の行列を用意します。




cz-sz00


szcz00


0010


0001


上記の行列の

  • sz は sin( r )
  • cz は cos( r )

です。また r はラジアンです。ラジアンは「角度 * π / 180」で求めることができます。

ここでは、45 度回転してみましょう。移動と同様に、WebGL のコードでは行と列の順番が入れ替わるため、回転のための行列は次のように用意します。

mat4 translate = mat4(
     cz,  sz, 0.0, 0.0,
    -sz,  cz, 0.0, 0.0,
    0.0, 0.0, 1.0, 0.0,
    0.5, 0.0, 0.0, 1.0
);

コードの反映すると vertex shader は次のように書くことができます。

precision mediump float;

attribute vec4 a_position;
uniform mat4 u_projectionMatrix;

void main() {
    const float PI = 3.1415;
    float r = 45.0 * PI / 180.0;
    mat4 rotate = mat4(
         cos( r ), sin( r ), 0.0, 0.0,
        -sin( r ), cos( r ), 0.0, 0.0,
              0.0,      0.0, 1.0, 0.0,
              0.0,      0.0, 0.0, 1.0
    );
    gl_Position =  u_projectionMatrix * rotate * a_position;
}

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

移動や回転をするために行列を用意しましたが、実は CSS からもっと簡単に入力することもできます。次回はその方法をまとめたいと思います。なお、その他の変換するための行列は、WebGL Basics 5 – Full transformation matrix « The Blog-o-Benが参考になるかもしれません。