Help us understand the problem. What is going on with this article?

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

More than 3 years have passed since last update.

この記事は、Unity 2 Advent Calendar 2016 の11日目になります。
10日目の記事は@kaiware007さんのAppendStructuredBuffer/ConsumeStructuredBufferを使ったGPUパーティクルのサンプルです。


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

今回はそのうちのテクスチャをあらかじめ準備しておく手法を用いた
このSpriteRendererのメダルの後光の加算部分での最適化事例をご紹介します。
キャプチャ0.PNG

目的

現在開発中のゲームではこのメダルが大量に出ますので
この目も当てられない描画負荷に対するアプローチが必要でした。
(※下記画像ではRippleエフェクトもかかってますので若干画面が揺らいでいます)
キャプチャ1.PNG

原因

当然ではありますが、通常、半透明と加算ではスプライトのバッチングは行われずSetPassの数も増えてしまいます。
キャプチャ.PNG

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

シンプルなアプローチ

単純に「加算レイヤー」と「半透明レイヤー」に分けることでバッチングを促します。
UnityスプライトではSortingLayerを使うことで簡単にレイヤー単位での描画プライオリティを作ることが出来ます。
(とりあえずシェーダーはプリセットのものを使用しています)
キャプチャ4.PNG

これによりメダル全体の描画を2パスに抑えることが出来ます。
キャプチャ2.PNG
これはこれで悪くはないのですが、メダルの上には加算がかからないので「特別な状況感」はやや薄れてしまいます。
やはり発光>メダル>発光>メダル>発光・・・という描画を諦めることが出来ませんでした。

事前乗算というアプローチ

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

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

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

そしてそれぞれのテクスチャをドロップしてブレンド方法を選択し、それぞれ保存します。
キャプチャ10.PNG
キャプチャ11.PNG


ここで一度に複数のテクスチャを登録するとテクスチャが事前に合成されます。
もし合成してしまえる場合はしてしまった方がフィルレートやバッチングコストを抑えれますので利用すべきです。
今回開発中のゲームではメダルが常時発光しているわけではないので事前合成は行いません。
キャプチャ12.PNG
キャプチャ13.PNG


そして作成されたPMAPテクスチャのスプライトをAtlasにまとめます。
※今回はUnityのSpritePackerを利用しますが別ツールでパッキングしてもいいと思います。
※PMAPテクスチャのAlphaTransparentフラグはOFFにしないと正常に表示されないので注意してください。
キャプチャ18.PNG

そして作成されてPMAPテクスチャの方のスプライトのマテリアルに
プリセットのParticle/Alpha Blended Premultiplyシェーダーを設定します。
キャプチャ20.PNG

長くなりましたがこれで完成です。
PMAP対応によって1Passで描画できていることが確認出来ます。
[適用前]
キャプチャ22.PNG
[適用後]
キャプチャ21.PNG

たくさん並べても1Passになっていることが確認できます。
キャプチャ3.PNG

まとめ

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

宣伝

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

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

Fuji0k0
Unityエンジニア
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away