11
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WebGLで円形ワイプエフェクトしてみた

Last updated at Posted at 2015-09-06

以下のサイトを見て面白そうだったので、WebGLでも円形ワイプエフェクトをしてみました。

・DirectXで円形ワイプエフェクト

円形ワイプはスーパーマリオなどでよく見かけたエフェクトですね♪
01.gif

ワイプエフェクトの仕方

ワイプエフェクトをするにはステンシルバッファを使います。
ステンシルバッファとはマスク処理のようなもので、以下のサイトを読めば詳しくわかると思います。

・wgld.org - ステンシルバッファ
・wgld.org - ステンシルバッファでアウトライン

今回の実装の流れとしては、ざっくりと以下のようになります。
1)ステンシルテストを有効にする
2)円を描画する(マスク用の描画)
3)表示したいテクスチャを描画する
4)ステンシルテストを無効にする

というわけでまずは円の描画します。
WebGLでは円の描画ができないので、10度ずつの三角形を36枚描画してみました。
(この円にアンチエイリアスのシェーダー適用したらもっと綺麗になるかも)
02.png
・WebGL-円描画・・・drawArraysで円描画のコード
・WebGL-円描画(インデックスバッファ)・・・drawElementsで円描画のコード
※ インデックスバッファの方は無駄に頂点を使わずに済む方式です

あとはこれをステンシルバッファに組み込めば完成です!
ついでにマウス操作できるようにしてみました。

・WebGL-ワイプエフェクト・・・マウス操作でワイプが動くコード
03.png

Live2D WebGLで実装してみる

Live2Dの場合は、内部のライブラリでステンシルテストが無効にされていました。
そのため上記方法では実装できませんでした。
ステンシルバッファを使うためにフレームバッファに一度描画してやる必要があります。
今回はフレームバッファを2枚使い、1枚目はLive2D描画、2枚目でステンシルバッファをしています。
04.png

・wgld.org - フレームバッファ

ただ、上記サイトの引数ではフレームバッファ上でステンシルバッファを使う事が上手くできず...。

そこでwgld.orgのdoxasさんに相談したら「デプスステンシル」という素晴らしいものを教えてもらいましたっ!
コード上では以下の引数がデプスステンシルに変わるだけです。

// レンダーバッファのフォーマット設定
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
// フレームバッファへのステンシルバッファの関連付ける
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencilrenderbuffer);

これでやっと実装が完了しましたっ!
05.gif
・Live2Dで円形ワイプエフェクトデモ

Live2Dでのソースコード

githubにソースをアップしたので、モデルとLive2DライブラリをDLすれば使えます。
https://github.com/naotaro0123/Live2D_Stencil

ハマったところメモ

はじめは円描画にdrawArrays()を使っていましたが、なぜか一部のLive2Dモデルではワイプエフェクトで描画する事はできなかった...。
(haru、wankoモデルはワイプエフェクトもできずLive2Dモデルも表示されない)
どうやらLive2D Cubism Modeler上でカリングがONになっていると描画できない事がわかりました。
Modeler上ですべての描画オブジェクトのカリングをOFFにして書き出せばワイプできました。
06.png

描画オブジェクトが1つでもカリングONになってると描画されずWebGLエラーも出なくて、gl.cullFace(gl.BACK)とかも効果なしで困りました。
たぶん、初期に作られたLive2DモデルはカリングONで作られていてこれで結構ハマりました...。

ただ、効率化のために円描画をdrawElements()に変えたら、全てのLive2Dモデルでワイプできたという。
理解不足でこの挙動は謎ですが、WebGLで描画する時は極力drawElements()使おうね!って事がわかりました。

その他の参考サイト

Direct3D ステンシルバッファって何?
OpenGL ステンシルバッファ

2015/12/02追記
フォーラムで関数が一部暗号化されていて使えなくて困ってる人がいたので、使えるようにしてもらいました。
Live2D Community - motion - set / get LOOP fade

11
12
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
11
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?