CSS Shaders はじめの 8歩目、ピクセルごとに異なる色
GraphicalWeb Advent Calendar 2012 の 13日目の記事です。
前回の記事では、fragment shader を利用しピクセルに色をつける方法を試しました。すべてのピクセルに対し同じ色を指定しただけでした。今回は、頂点ごとに異なる色をつける方法を少し試してみます。
まず、vertex shader では、頂点ごとに異なる a_position や a_meshCoord などの attribute 変数を利用することができました。しかし fragment shader では attribute 変数は利用できません。頂点ごとに異なる情報を fragment shader に渡したい場合には、vertex shader を経由して、そこから fragment shader に変数を渡すことになります。
vertex shader から fragment shader に変数を渡すときには、varying 変数を利用します。
uniform 変数|CSS から vertex shader と fragment shader に固定の情報を渡す
attribute 変数|CSS から頂点ごとに異なる情報を vertex shader に渡す
varying 変数|vertex shader から頂点ごとに異なる情報を fragment shader に渡す
varying 変数を試すために次の簡単なサンプルを用意してみました。
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;
// fragment shader に渡すために varying 変数を宣言
varying vec4 v_color;
void main() {
float z = sin( a_meshCoord.x * 3.1415) * 100.0;
vec4 pos = vec4( a_position.xy, z, a_position.w );
// a_position を v_color に代入して fragment shader に渡す
v_color = a_position;
gl_Position = u_projectionMatrix * u_transform * pos;
}
fragment shader
precision mediump float;
// vertex shader から受け取るために varying 変数を宣言
varying vec4 v_color;
void main() {
css_MixColor = v_color;
}
すると vertex shader では座標として利用されていた vec4 が fragment shader でそのまま色へ利用されます。
ここまでの状態の demo(2012年 12月現在では CSS Shader を有効にした Chrome 25以降である必要があります。)
vec4 が色として利用される場合は vec4( red, green, blue, alpha ) なので、キャプチャー上では
- 左上の座標は x = 0, y = 0, z = 0 で vec4( 0.0, 0.0, 0.0, 1.0 ) なので不透明の黒
- 右上の座標は x = 1, y = 0, z = 0 で vec4( 1.0, 0.0, 0.0, 1.0 ) なので不透明の赤
- 左下の座標は x = 0, y = 1, z = 0 で vec4( 0.0, 1.0, 0.0, 1.0 ) なので不透明の緑
となっているのが確認できます。