WebGLでエロゲー風に部分モザイクしてみた

ステンシルバッファ（マスク処理）にシェーダー適用して、部分的にモザイクさせてみました。
Live2D WebGL版と合わせるとこんな感じにできます♪
（エロゲー用の素材を持っていないので公式サンプルでテスト）
![001.gif](https://qiita-image-store.s3.amazonaws.com/0/15028/bcc7a448-a710-e6f2-d646-8fe0c49ff9de.gif)
[・Live2Dで部分モザイクデモ](http://simplecode.jp/testcode/Live2D_Mozaiku/index.html)

上記デモページでは、モーション切替とモザイク箇所の切替ができます。
モザイクは一部の描画オブジェクトごとにかけられるように実装しています。
そのため、描画オブジェクトが動くとモザイク部分も動きますっ！
![002.png](https://qiita-image-store.s3.amazonaws.com/0/15028/ec11f016-e78d-032b-8449-00c01ee99a9c.png)

WebGLの技術としては、以下のものを使いました。
１）モザイクシェーダー
２）ステンシルバッファ
３）フレームバッファ
４）Live2DのWebGL描画

# 開発環境
・Live2D WebGL SDK 2.0.04_1
・SDKのSimpleプロジェクトをカスタム

# モザイクシェーダー部分の実装
モザイクシェーダーは以下の記事を参考にさせていただきました。
[・Qita - GLSLでモザイク処理](http://qiita.com/edo_m18/items/d166653ac0dccbc607dc)

GLSLでたった4行でモザイクが実現できるのは驚きですねっ！
これをテクスチャに実装するとこんな感じです。
![003.png](https://qiita-image-store.s3.amazonaws.com/0/15028/aa0adca9-4928-f818-af22-99640a74a3af.png)
[・WebGL-モザイク](http://jsdo.it/.naotaro/5nZz)・・・モザイク適用したコード

# ステンシルバッファ部分の実装
ステンシルバッファは、マスク用のテクスチャを描画し、その上に2枚目のテクスチャを描画する方法で実装しました。
マスク用のテクスチャは目の部分だけ描画してるので、目の部分だけくり抜くマスクができます。
テクスチャ描画だけでなく、三角形などの描画でもマスク用に使えてワイプエフェクトなどもできます。

テクスチャ2枚使って実装するとこんな感じです。
![004.png](https://qiita-image-store.s3.amazonaws.com/0/15028/c2fa89fc-3a60-9b06-f0ff-b7af7007583e.png)
[・WebGL-ステンシルバッファ](http://jsdo.it/.naotaro/fWrf)・・・ステンシルバッファのコード

# フレームバッファ部分の実装
テクスチャ1枚をフレームバッファで実装するとこんな感じです。
[・WebGL-オフスクリーン](http://jsdo.it/.naotaro/2S8q)・・・フレームバッファのコード

フレームバッファは描画結果を加工するために4枚使いました。
まず、Live2Dライブラリの中でステンシルもオフになっているので、フレームバッファを使わないと何もできません。

　フレームバッファ1枚目：Live2D描画用
　フレームバッファ2枚目：ステンシルバッファ用
　フレームバッファ3枚目：モザイクシェーダー用
　フレームバッファ4枚目：ステンシルとモザイク合成用

# ステンシルにシェーダー適用し合成の実装
ステンシルバッファにシェーダーを適用し、テクスチャ画像と合成してみました。
カラー反転シェーダーで実装するとこんな感じになります。
![005.png](https://qiita-image-store.s3.amazonaws.com/0/15028/c2b3ba33-1447-4c10-90e1-95752d7128bf.png)
[・WebgL-ステンシルとポストエフェクト](http://jsdo.it/.naotaro/2EIH)・・・ステンシルとエフェクト合成のコード

# Live2D WebGLで実装してみる
実はLive2D SDKでは、描画オブジェクトの頂点情報が取れます。
取得できた頂点を繋いでマスク用の図形を描画しました。
[・Live2D Manual - 頂点インデックスの取得](http://sites.cybernoids.jp/cubism2/sdk_tutorial/live2d_library/load_to_display/cd/ding-dianindekkusuno-qu-de)

```js:
// 描画オブジェクトIDからインデックス取得
var drawIndex = live2DModel.getDrawDataIndex("描画オブジェクトID");
// 頂点位置を取得
var points = live2DModel.getTransformedPoints(drawIndex);
```

本当は頂点インデックスも取りたかったけど、JavaScriptではlive2dModel.getIndexArray()が見えない...orz
そのため、インデックスバッファを使わないで描画しています。
ちなみにUnityでは頂点インデックスが取れたので、JSではこの関数は存在するが暗号化されているのか取れないようです。
（Unityではこちらのコードで取れます　→　[Qita - Live2DモデルファイルからパラメータID取得](http://qiita.com/naotaro0123/items/e729af19c9c9f550c715)）

また、頂点情報がCanvas座標で返ってくるのでWebGL用の座標に正規化しています。

```js:
var w = live2DModel.getCanvasWidth();
var h = live2DModel.getCanvasHeight();
var p = w / h;  // ModelerのCanvas縦横サイズが違うもの対応
var vertex_cnt = 0;
// 初期化
for (var j = 0; j < points.length; j+=2) {
    // Canvasの解像度位置で返されるので、WebGL用に-1.0〜1.0の値に正規化
    that.object_pro.object_pos[vertex_cnt]   = ((points[j] * 2.0 - w) / w) * p;
    that.object_pro.object_pos[vertex_cnt+1] = ((points[j + 1] * 2.0 - h) / h);
    that.object_pro.object_pos[vertex_cnt+2] = 0.0;
    vertex_cnt+=3;
}
```
頂点情報以外の部分は、前回書いた[WebGLで円形ワイプエフェクトしてみた](http://qiita.com/naotaro0123/items/45a30b006eab9d9a1b42)とほぼ一緒です。

これでLive2D＆WebGLでエロゲが作れる事が証明できましたっ！

# Live2Dでのソースコード
githubにソースをアップしたので、モデルとLive2DライブラリをDLすれば使えます。
[Live2D-Mozaiku](https://github.com/naotaro0123/Live2D-Mozaiku)