CSS Shaders はじめの 9歩目、座標に応じた影っぽい色
Posted :
GraphicalWeb Advent Calendar 2012 の 14日目の記事です。
前回の記事では、頂点に対応する色を vertex shader から fragment shader に送ることができることを紹介しました。今回は、この仕組みを利用し、影らしき着色をしてみます。
今回用意したサンプルは以下です。前回と違うのは、vertex shader の色を受け渡す部分 1行のみです。
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 );
// z の高さ ( 0 ~ 100 ) に応じて、透明度の異なる黒を fragment shader に送る
v_color = vec4( 0.0, 0.0, 0.0, min( 0.75, 1.0 - ( z / 100.0 ) ) );
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 によりメッシュ (HTML の要素) の頂点は変換され、z 方向については、0 から 100 の間で出力されています。そこで、これを利用し「z が 0 に近ければ暗く、100 に近ければ明るい」という簡素な影らしき表示をしています。(リアルな影なら光の方向と法線の方向から計算するべきですが..。)
これにより、上記の vertex shader の
// z の高さ ( 0 ~ 100 ) に応じて、透明度の異なる黒を fragment shader に送る
v_color = vec4( 0.0, 0.0, 0.0, min( 0.75, 1.0 - ( z / 100.0 ) ) );
では、色は 0, 0, 0 で黒の固定、透明度は min( 0.75, 1.0 - ( z / 100.0 ) )
で z
の値に応じて v_color
へ代入されます。
z
が0
ならvec4( 0.0, 0.0, 0.0, min( 0.75, 1.0 - ( 0.0 / 100.0 ) );
で 75% 不透明の黒色z
が50
ならvec4( 0.0, 0.0, 0.0, min( 0.75, 1.0 - ( 50.0 / 100.0 ) );
で 50% 半透明の黒色z
が100
ならvec4( 0.0, 0.0, 0.0, min( 0.75, 1.0 - ( 100.0 / 100.0 ) );
で透明の黒色
といった具合に色が fragment shader に渡されることになり、これによりそれっぽい感じにみせることができています。
ここまでの状態の demo(2012年 12月現在では CSS Shader を有効にした Chrome 25 以降である必要があります。)
CSS3 3D Transforms も CSS Shader に似た 3次元の変換はできるのですが、同時に影を表現することはできません。しかし、CSS Shaders なら変換に応じた影の表現もできるのです。