こんにちは、yohei kojima です。
今回はWebGLを使ってポスタリゼーションの実装をしたのでその解説をしていきます。
WebGLというと3Dのゴリゴリしたものを作るイメージですが、2Dでも活用できたりします。今回は画像や動画を加工するポスタリゼーションというものを紹介します。
まえがき
WebGLアドベントカレンダーではないのでWebGLについて簡単に解説しておきます。
WebGLはJavaScriptのAPIの1つで2Dや3Dのグラフィックスをレンダリングするためによく使われています。また、three.js はWebGLを扱うライブラリの1つでとても有名です。簡単に3Dなサイトが作れます(たぶん)。
・WebGLを使っているサイト
http://campoallecomete.it/#!/en
http://lightgraffiti.littlesun.com/
・WebGL参考サイト
Three.js入門サイト - ICS MEDIA
WebGL 開発支援サイト wgld.org
デモ
先にデモを載せておきます。(今回webcameraはスマホで動かないです。スミマセン)
https://youhe.jp/demo/posterization/
・GUIの説明
original -> オリジナル表示のON / OFF
webcamera -> webカメラのON / OFF
mono -> 白黒のON / OFF
threshold -> 階調数を変更するしきい値
解説
ポスタリゼーションとは階調変更と言われる画像処理です。WebGLでいうとポストエフェクトの1つになります。
画像はRGBそれぞれ0~255の256階調で表されており、この256階調を変更することがポスタリゼーションです。階調数を変えるとイラストっぽい表現ができたりします。
・RGBのRを階調変更した例
256, 16, 8, 4の順で階調数を減らしています。
この処理を1pxごとのRGBに行うとデモが作れます。
ソースコード解説
シェーダーだけコメントアウトで解説します。
precision highp float;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
attribute vec3 position;
varying vec2 vTexCoord;
void main() {
// position.xy を正規化してフラグメントシェーダーに渡す
vTexCoord = (position.xy + 1.0) / 2.0;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
precision highp float;
uniform sampler2D imgTxt; // 画像テクスチャ
uniform float threshold; // しきい値
varying vec2 vTexCoord;
// 写像について
// http://twilightdve.hatenablog.com/entry/2014/06/23/142555
float map(float val, float s1, float e1, float s2, float e2) {
return s2 + (e2 - s2) * ((val - s1) / (e1 - s1));
}
float posterize(float v) {
// v には 0.0 ~ 255.0 の値が入っています。
// これを 0.0 ~ threshold に写像を使って変換します。
float m = map(v, 0.0, 255.0, 0.0, threshold);
// floorで整数にしたあと階調数で割る
float f = floor(m) / (threshold - 1.0);
// 0 ~ p未満 の整数を返します。
return f;
}
void main() {
// テクスチャから色情報を取得
// RGBは 0 ~ 255 で表すことが多いのですが、
// texture2D では 0.0 ~ 1.0 の値が返されます。
vec4 destColor = texture2D(imgTxt, vTexCoord);;
// RGBを別々に処理します。
// 今回はわかりやすいように * 255.0 して
// 0.0 ~ 255.0 の値を posterize に渡します。
destColor.r = posterize(destColor.r * 255.0);
destColor.g = posterize(destColor.g * 255.0);
destColor.b = posterize(destColor.b * 255.0);
// ポスタリゼーションの処理をした色を出力
gl_FragColor = vec4(destColor.rgb, 1.0);
}
※ webカメラや白黒の判定などポスタリゼーションに関係のないソースは除外しています。
あとがき
今回はポスタリゼーションの紹介でしたが、他のポストエフェクトを合わせるとよりイラストっぽい表現ができます。
https://youhe.jp/jiyuchou/illustration/
WebGLやってみてね。