[Unity]加算と半透明を1パスにするP-MAPブレンド実用例

この記事は、[Unity 2 Advent Calendar 2016](http://qiita.com/advent-calendar/2016/unity2) の11日目になります。
10日目の記事は@kaiware007さんの[AppendStructuredBuffer/ConsumeStructuredBufferを使ったGPUパーティクルのサンプル](http://qiita.com/kaiware007/items/fc77ab303a326123344b)です。

***

CEDEC2015においてP-MAPブレンドによる加算合成のアプローチの講演、およびサンプルプロジェクトが公開されました。
http://cedec.cesa.or.jp/2015/session/ENG/1024.html
http://www.slideshare.net/toshiyasumiyabe/cedec2015pmap

今回はそのうちのテクスチャをあらかじめ準備しておく手法を用いた
このSpriteRendererのメダルの後光の加算部分での最適化事例をご紹介します。
![キャプチャ0.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/5e0d8092-abc8-dd89-200f-06c42d3e5001.png)

#目的
現在開発中のゲームではこのメダルが大量に出ますので
この目も当てられない描画負荷に対するアプローチが必要でした。
（※下記画像ではRippleエフェクトもかかってますので若干画面が揺らいでいます）
![キャプチャ1.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/80842659-cd5e-5c4e-2f99-d61c39f240b1.png)


#原因
当然ではありますが、通常、半透明と加算ではスプライトのバッチングは行われずSetPassの数も増えてしまいます。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/0a0bc755-e254-ff6b-b321-a317c4cf4130.png)

大量にメダルが重なった場合は加算＞半透明＞加算＞半透明＞加算･･･とメダル数×２の描画数（＝SetPass数）が発生してしまいます。
頻繁に起きる状況ではありませんが対策をしない場合、
特にAndroidにおいて操作出来ないほどの処理落ちや発熱による機能低下が発生してしまいます。

#シンプルなアプローチ
単純に「加算レイヤー」と「半透明レイヤー」に分けることでバッチングを促します。
UnityスプライトではSortingLayerを使うことで簡単にレイヤー単位での描画プライオリティを作ることが出来ます。
（とりあえずシェーダーはプリセットのものを使用しています）
![キャプチャ4.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/b9cd36ed-1f3c-794a-8263-4fe62e3ec0dd.png)

これによりメダル全体の描画を2パスに抑えることが出来ます。
![キャプチャ2.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/a53e2c4d-6332-51f2-91ca-ef25e6a8bbad.png)
これはこれで悪くはないのですが、メダルの上には加算がかからないので「特別な状況感」はやや薄れてしまいます。
やはり発光＞メダル＞発光＞メダル＞発光･･･という描画を諦めることが出来ませんでした。

#事前乗算というアプローチ
加算＞半透明＞加算＞半透明＞加算･･･という描画を現実的に実装するには
同一のシェーダーで行えるようにしなればなりません。
ここで掲題のP-MAPブレンドが登場します。

発表されている内容にはテクスチャに手を加えないシェーダーでのブレンドもありますが
開発中のゲームはモバイルで、適用対象は大量のスプライトであった為、
シェーダー内での計算量は極力抑える必要がありました。
なので事前にテクスチャを作成するP-MAPテクスチャの手法を採用しました。
https://github.com/ToshiyasuMiyabe/P-MAP
////////////////////////////////////////////////////////////////////////////////
以下GitHubより抜粋
![キャプチャ5.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/bb56f0b5-ad0a-9736-f0e9-3b76969471a7.png)
////////////////////////////////////////////////////////////////////////////////

それでは実際に扱う準備をしていきます。
GitHubで公開されているプロジェクトからPMAP.csとPMAP_Maker.csを自身のプロジェクトに移しましたら、
UnityのウィンドウメニューにPMAPが追加されますので選択してPMAP_Makerウィンドウを開きます。

そしてそれぞれのテクスチャをドロップしてブレンド方法を選択し、**それぞれ保存**します。
![キャプチャ10.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/c627af8d-5478-6ab0-5a70-689aa9566092.png)
![キャプチャ11.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/db4c458a-ab52-2ae4-9da7-885a59da209a.png)
***
ここで一度に複数のテクスチャを登録するとテクスチャが事前に合成されます。
もし合成してしまえる場合はしてしまった方がフィルレートやバッチングコストを抑えれますので利用すべきです。
今回開発中のゲームではメダルが常時発光しているわけではないので事前合成は行いません。
![キャプチャ12.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/1c9610d9-601d-00ab-060c-047c7ed6dabf.png)
![キャプチャ13.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/90099674-372c-c176-1d74-2359a745ee44.png)
***
そして作成されたPMAPテクスチャのスプライトをAtlasにまとめます。
※今回はUnityのSpritePackerを利用しますが別ツールでパッキングしてもいいと思います。
※PMAPテクスチャのAlphaTransparentフラグはOFFにしないと正常に表示されないので注意してください。
![キャプチャ18.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/2e2b5902-d5fb-980d-79c1-a714de95b8d7.png)

そして作成されてPMAPテクスチャの方のスプライトのマテリアルに
プリセットのParticle/Alpha Blended Premultiplyシェーダーを設定します。
![キャプチャ20.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/903b23bc-7064-16de-3ed8-24250570b1eb.png)

長くなりましたがこれで完成です。
PMAP対応によって1Passで描画できていることが確認出来ます。
**[適用前]**
![キャプチャ22.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/d81db330-2516-f256-a379-ed4d10acd813.png)
**[適用後]**
![キャプチャ21.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/3cd49943-bc24-478f-3db7-51d8ec280351.png)

たくさん並べても1Passになっていることが確認できます。
![キャプチャ3.PNG](https://qiita-image-store.s3.amazonaws.com/0/105136/12399406-3ce3-4578-0120-ac01aa1a998e.png)


#まとめ
今回はCEDEC2015でナツメアタリ株式会社、宮部様が講演され、
GitHubで公開されているPMAP_Makerの使用方法と実用例をご紹介しました。
なお事例として紹介しています開発中のゲームにおいてはさらに少し手を加えて
独自のツール（というよりはオレオレツールですが）とシェーダーになっていますが
アプローチ方法としては今回ご紹介したP-MAPテクスチャを基にさせて頂いています。

#宣伝
今回事例としてご紹介しました開発中のゲームは
株式会社タノシマスのiOS/Android用シューティングゲームの「[アカとブルー](http://tanoshimasu.com/project)」になります。
ご興味を持ってくださった方は是非動向を追って頂けましたら幸いです。
https://twitter.com/tanoshimasu_com
https://www.youtube.com/watch?v=rrfZkyd438I
https://www.youtube.com/watch?v=o83B-dm5JA8


長々とお読みいただきましてありがとうございました。