LoginSignup
18
16

More than 5 years have passed since last update.

GLSLでモザイク処理

Posted at

自分のところから出たものであれですが、Filtersはほんとに面白いです。
GLSLを楽しく学ぶには打ってつけ。

今回はそこでフォークして作ったモザイクについて書きたいと思います。
こうしたテクニックを覚えておくと、あとあと別のことに流用できたりするので基礎はやはり大事ですね。

さて、前回の記事で書いたピンポイントモザイクフィルター

ピンポイントモザイクフィルター

図形の描画は前回の記事で書いたものをそのまま使っています。
問題のモザイク部分は、カメラからのテクスチャの色を取得するときのロジックをいじってやることで実現しています。

モザイク処理

モザイク処理、これ自体は実はFiltersに投稿されていたものをフォークして作っています。
Filtersのいいところは、こうして自分が作りたいフィルターのベースを見つけてフォークできる点ですね。
あとはもう、どういう発想ができるか、が面白いフィルターを作れるか否かの分岐点でしょう。

さて、その問題のモザイク処理ですが、最初はどんなことをやっているんだろうと思いながらフォークしました。
そして箱を開けてみてびっくり! その処理の単純さに驚きました。

実際のコードを見てもらうと分かると思います。

void main()
{
    vec2 uv = iScreen;
    uv = floor(uv * iSize * 15.0) / 15.0 / iSize;
    vec4 color = texture2D(iCamera, uv);
    gl_FragColor = vec4(color.rgb, 1.0);
}

なんと4行!

しかも、実質モザイクの計算をしているのは以下の1行だけです。

uv = floor(uv *  iSize * 15.0) / 15.0 / iSize;

めっちゃシンプル。
ちなみにiSizeはピンチイン・アウトのサイズが入ってくるので、もしピンチイン・アウトの対応をしない場合はさらに簡潔になります。

uv = floor(uv * 15.0) / 15.0;

これでモザイクになってしまうのだからGLSLは奥が深いですね。
さて、なにをしているかというと、uvはテクスチャの、いわゆる「UV座標」と呼ばれるものです。
名前からも分かりますね。

そして、仮に細工をせずにこれをそのまま使えばカメラで撮影した絵がそのまま出力されます。
それを、なにか細工をしてから使用していますね。

やっている処理はいったんuv15.0をかけ、その端数を切ります(floor関数)。
そのあとで、かけた値で割ります。

例えば0.5の座標だとした場合、floor(0.5 * 15.0) / 15.0ですね。

floor(0.5 * 15.0) = 7.0; // 7.5の端数を切る
7.0 / 15.0 = 0.466666...

となります。

さて。0.5で計算しましたが、0.48と微妙に小さい数字の場合はどうなるでしょうか。
実は計算結果は一緒になります。
なぜなら、floor(0.48 * 15.0) = 7.0だからです。
つまり、この計算結果が7になる間は同じ座標の色を使うことになります。

そしてモザイクのサイズは15.0の値によって決まります。(15.0以外にするとモザイクのサイズが変わる)
これがモザイク処理の正体です。

いやーうまく出来てるもんです。

余談

ちなみに、GLSLは基本的に-1〜1の間の数値を扱います。
これは、画面サイズがどんなに大きくても、最大でx, yともに1になる、ということです。
つまり、0.02というのは小さいように見えて意外と大きな数値です。
こうしたところからも、上記のような計算が成り立つ理由になっています。

ほんとよく出来てますね。

18
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
16