テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

【Unity】iOSでASTCフォーマットのテクスチャ圧縮を使う

今回はPVRTCと比較して割と綺麗で消費メモリも少ないASTCフォーマットのテクスチャ圧縮を使用する方法についてです。

ASTCについて

wlog.flatlib.jp

ブロックの大きさを指定可能で、ブロックのサイズが大きければ大きいほど圧縮率が高く、汚くなります。

PVRTCが1ピクセルを4ビットで表現しているのに対し、ASTC 6x6は3.56ビット、ASTC 12x12は0.89ビットという高圧縮率を誇ります。また、最も圧縮率が低くTrueColor並に綺麗なATSC 4x4でも1ピクセル8bitと、割とコンパクトに収まります。

f:id:tsubaki_t1:20160928235251j:plain

developer.nvidia.com

ASTC を使用する

f:id:tsubaki_t1:20160928234909p:plain

 

ASTCとPVRTCとTrueColorを比較してみる

5.5からだと思いますが、ASTCがiOSでも使用できるようになりました。

実際にiPad proに出力した物を比較してみます。

True ColorとATSC 4x4を比較すると、殆ど見分けはつかないレベルです。これでも消費メモリは半分以下になります。

PVRTCとASTC6x6は大体消費メモリは同じくらいですが、内側に滲んでいるPVRTCと比較してASTC 6x6の方が綺麗に見えます。
ASTC12x12まで行くと非常に汚く見えるようになりますが、消費メモリはガッツリと落ちます。

f:id:tsubaki_t1:20160928235440j:plain

 

使えるのはA8以降のCPU

割と綺麗なASTCですが、使用する為にはA8以上(iPhone6以降)のCPUが必要となります。
ソレ以前のA7のCPUを使用するとTrueColorに解凍し展開するため、汚くロードも長い割にメモリを超喰うという踏んだり蹴ったりな状況になります。

 

実際に解凍できなかった場合、以下のようなメッセージが表示されます。
WARNING: ASTC texture format is not supported, decompressing texture

 

AndroidでのASTC対応端末は、ココが参考になるかもしれません。

OpenGL ES Hardware Database - © 2013-2015 by Sascha Willems

 

関連

tsubakit1.hateblo.j

【Unity】uGUIのImageとSprite Rendererの使い分け

今回はuGUIのImageとSprite Rendererの使い分けについてメモします。

 

ImageとSprite Renderer

Unityで2Dの絵を簡単に出す方法として思いつくのが、Sprite Rendererのような2D機能を使用する方法と、uGUIのImage系の機能を使用する方法です。

どちらも「テクスチャを表示する」という振る舞いなので、画面に表示したようなケースでは、全く見分けが付きません。

f:id:tsubaki_t1:20160924204917j:plain

では、どちらを使っても良いのかと言われれば、まぁどちらを使っても良いのですが、有利な点・不利な点があります。

 

Sprite Rendererの振る舞い

Sprite Rendererは、それ単体でアセットを描画する機能を持ったレンダラーです。Sprite(アセット)に設定したポリゴン情報を元に、描画を行います。

描画順の制御にはSorting LayerとOrder In Layerを使用した単純な物になっており、座標もTransform準拠と、Unityの基本機能を少し拡張したような内容になっています。

f:id:tsubaki_t1:20160925025332j:plain

Sprite Rendererを使用するには、2Dモード時にSpriteをScene Viewへドラッグ&ドロップするという簡単な方法で使用できます。

 

uGUI Imageの振る舞い

uGUIのImageは、CanvasRendererとCanvasとの組み合わせで描画する機能です。
Sprite(アセット)に指定したTextureとUV情報を元に、描画を行います。

描画の制御は、Hierarchyの順番に依存しますが、同時にCanvasに設定したSorting LayerとOrder in Layerによる描画順制御も行います。

座標はRectTransformと呼ばれるTransformを拡張したアセットが使用されます。サイズの変更はWidth/Heightにより行われ、Scaleを使用するとレイアウト機能が破綻する事が多いです。

f:id:tsubaki_t1:20160925030900j:plain

uGUIのImageを使用したい場合、まずCanvasオブジェクト以下にImageを含むオブジェクトを作成し、Spriteを設定するといった手順になります。

 

最適化に関するアプローチの違い

最終的にはSpriteを表示するという点で似たような機能ですが、アプローチは全く異なっており、利用するケースが異なります。

f:id:tsubaki_t1:20160925231634j:plain

 

SetPassの削減に関する振る舞いの比較

2Dにおいてパフォーマンスを稼ぎたい場合、一番目につく項目はSetPassの削減です。基本的にSetPassは少なければ少ないほど良いです。SetPassの数は、ProfilerのRendererやGameViewのStatsから確認出来ます。

f:id:tsubaki_t1:20160925221327j:plain

 

Sprite RendererのSetpass削減ですが、基本的にDynamic BatchingとAtlas化に依存します。

この機能は他の3D描画機能の延長で作成されており、Atlasでマテリアルを切り替える回数を可能な限り削減し、Batchingでメッシュを纏めて一括描画を行います。
逆に、Atlasが異なるスプライトが描画順に挟まるとSetPassは増えます。

f:id:tsubaki_t1:20160925222116j:plain

f:id:tsubaki_t1:20160925224643j:plain

 

Canvas Imageの場合、実はAtlasが別でもSetPassは1です
但しAtlas化が無意味という訳ではなく、一応Batchingの実行数に影響します。但し、パフォーマンスの影響的にはSetPassの方が重要なので、誤差の範囲です。

なおシーン内に複数のCanvas持つ場合、Canvasの数に応じてSetPassも増加します。また、UIのMaterialに他のマテリアルを設定すると、ソコは別に描画されるためかSetPassが増加します。

f:id:tsubaki_t1:20160925230551j:plain

 

フィルレート・オーバードロー削減に関する振る舞いの比較

特に高解像度かつGPUが低スペックなモバイル環境下では、オーバードロー(何度も描画する)は非常に大きな問題になります。

また、Power VRを使用した端末(iPhone等)の場合はCutoutも苦手としているので、重なるようにモデルやUIを配置するのは、非常に無駄と言えます。

f:id:tsubaki_t1:20160925231120j:plain

 

Sprite Rendererの場合、透明情報を元にポリゴンを作成します。テクスチャの解像度が高い場合は(キッチリくり抜く)ハイポリを、テクスチャ解像度が低い場合はローポリなメッシュを作成します。
透明部分をキッチリくり抜いてくれるのでオーバードローは削減出来ますが、代わりにポリゴンが少し増えます。

オプションとしてFullRect(ポリゴンでくり抜かない)を選択出来ますが、下の画像を見ての通り、オーバードローの範囲が増えやすくなります。 なお、この際にエディタで作成するポリゴンは調整出来ません。2D Experimentalでは可能なので、2D Experimental が統合されたら追加されそうです。

f:id:tsubaki_t1:20160925232628j:plain

f:id:tsubaki_t1:20160925232634j:plain

 

uGUIのImageの場合、基本的に四角形で切り抜きます。

またSliceした際に中央を塗らないというオプションがあります。このポリゴンに穴を開ける処理は将来的にはSprite Rendererでも似たようなことが出来るようになると思いますが(2D Experimental で動作を確認出来る)、現状ではuGUIのみ使用できるみたいです。

http://cdn-ak.f.st-hatena.com/images/fotolife/t/tsubaki_t1/20150324/20150324015719.png

 

またFullRectと異なり、透明の範囲をQUADでくり抜きます。

f:id:tsubaki_t1:20160926010927j:plain

 

大量に描画した時と動かした時の振る舞いの比較

uGUIのImageとSprite Rendererの最大の違いは、大量に描画した時と動かした時です。

 

まずSprite Rendererを利用して描画する場合、描画一つ一つに描画コストが発生するため、量が増えれば増えるほど描画負荷が上がります。

例えば256x256程度のスプライトを5000個程描画しようと思うと、自分のPCでは大体1.6~2.0msの描画コストが発生します。

ですが、Spriteを移動・変形・回転させた時のコストは、殆ど無いです。

f:id:tsubaki_t1:20160926001454j:plain

 

逆にuGUIのImageを描画する場合、動かさないならばCanvasに収集したCanvas Rendererの描画結果を使いまわすので、スプライトの個数が増えても描画コストは殆ど増えません。

Sprite Rendererと同じスプライトを1万2000個程度描画した場合でも、描画コストは0.2ms前後です。

f:id:tsubaki_t1:20160926002306j:plain

 

但し、Canvas以下のImageにに対し一つでも移動・変形・回転を行った場合、膨大な処理コストが発生します。

下画像の左の青い部分がソレで、5000個程度のImageのうち一つのImageをアニメーションさせると、大体71msという致命的なレベルの時間、処理が停止しました。

5個10個ならまだ無視しても良いのですが、もっと量が多いと非常に強力なボトルネックになりそうな予感があります。

この辺りはUnity 5.2で大分早くなりましたが、量が増えるとやはり問題になります。もっとコストを上げたければPixel Perfectにチェックをどうぞ。

f:id:tsubaki_t1:20160926003013j:plain

 

幸いなことに、動かすImageにCanvasを付けておく事で、動かした際のコストは激減します(上画像の右側)
但し、CanvasのEnable/Disableを切り替えると親Canvasが再構築を始めるので、そのあたりも注意です。(CanvasではなくImageをdisableする事で問題を最小に)
また、World Space / Screen Space Camera のUIの状態で、Canvasの座標・スケール・回転を操作した場合も再構築を始めるので、そっちも注意です。

 

つまり、どのように使い分けるべきか

つまるところ、

  • uGUIは動かすことを余り想定していない
    動かさなければ、低負荷 低消費電力
  • uGUIはCanvas単位で動かす
  • Spriteは動かすことを前提
  • 沢山描画する場合に対して最適化

といった方針が見えます。

また実際には

  • 動かさないがα0の範囲が大きいならSprite Renderer
    (但し、矩形できれいに抜ける場合はその限りではない)
  • スプライトを常に大量に動かすならSprite Renderer
  • オーバードローが多いならSprite Renderer
  • 画像を絶対に動かさないならuGUIのImage
  • 小さいスプライトを一部動かすならuGUIのImage
    (動かすImageは別途Canvas必須)

といった感じで使い分けるのが良さそうです。

この感じだと、実はSprite RendererでUI作ったり、ImageでSTG作るのも実はアリなんじゃないかなって思わなくもなくもなくも。(個人的な感想

 

Tips

  • Sprite RenderのレイヤーはSpriteRendererを設定したオブジェクト
    ImageのレイヤーはCanvasを設定したオブジェクト
  • CanvasにImageを設定すると、CanvasのサイズにフィットしたImageが作られる。World Spaceでとりあえず壁に絵を貼るときに便利
  • Canvas内のImageの一部でもCameraに写っているとCanvas内の全Imageが描画される。カリングはCanvas単位
  • 忘れがちだが、CanvasにSorting LayerとOrder In Layerが付いてる

関連

 

tsubakit1.hateblo.jp

tsubakit1.hateblo.jp

【Unity】Unity 5.5以降のRender Pathの設定

f:id:tsubaki_t1:20160926015348j:plain

Unity 5.5でRender Path(ForwardやDeferredを設定してたアレ)の表示がPlayer Settingsから別の場所へ移動しました。

新しいRender Pathの設定場所

新しい場所は、Project Settings > Graphicsの…ココ。

f:id:tsubaki_t1:20160926015449g:plain

見つけられるか…ッッッ

とりあえずボタンのUI以外にボタンを入れるのをやめよう(期待

 

Standard Shader Qualityの設定も

f:id:tsubaki_t1:20160926020330j:plain

 

あと、今までPCはHigh モバイルはLowを半ば強制されていたStandard Shaderのクォリティをココで調整出来るようになりました。

ココでモバイル向けにStandard Shaderのクォリティを上げ(多分CPU・GPU負荷がかなり上昇)するも良し、逆にモバイルで綺麗に見えるようにPCでStandard ShaderのQualityをLowにして調整するも良し(多分とても大変)

f:id:tsubaki_t1:20160926020238j:plain

 

関連

tsubakit1.hateblo.jp

【Unity】UnityでARToolKitを使ってみたら、意外と簡単だった

f:id:tsubaki_t1:20160924183636j:plain

今回はARToolKitを試してみたので、そのあたりメモします。

 

AR界のARToolKit

ARToolKitは、マーカーを追跡するAR(Augmented Reality)の代表的なライブラリの一つです。他にはvuforiaやSmartAR等が思いつきます。

世の中に出ている「マーカーを追跡するAR」で実際にリリースされているプロダクトでは、個人的には、大体ARToolKitかVuforia、SmartARが使われてる印象です。
 

Unity対応のARLoolKitが対応するプラットフォームは、 Windows, Mac OS X, iOS, Android みたいです。

 

C言語で挑戦したい場合は、下の記事が参考になりそうです。

「攻殻機動隊」「電脳コイル」の世界を実現! - ARToolKitを使った拡張現実感プログラミング - 工学ナビ

 

実際に使ってみる

ARToolKitは公式でUnityライブラリを提供しており、割と簡単に使えます。

試した環境はUnity 5.5b3ARToolKitのバージョンはARUnity5-5.3.2です。

 

パッケージの入手

まずはパッケージを入手します。

Download the ARToolKit Augmented Reality SDK | ARToolKit.orgのリンクより、Download Aditional Unity Toolを選択します。
その時、OSXWindowsか聞かれるので、Unityエディタを動かすプラットフォームを選択します。f:id:tsubaki_t1:20160922182627j:plain

 

ダウンロードしたファイルを解凍すると、こんな感じです。

f:id:tsubaki_t1:20160922183152j:plain

インポート

パッケージをインポートします。ARUnity5.UnitypackageをProjectビューへドラッグ&ドロップすればOKです。

その際、APIのアップデート確認が聞かれるかもしれませんので、I Made a Backup, Go Ahead!を選択します。

f:id:tsubaki_t1:20160922183720j:plain

インポートが完了すると(他に何もインポートしていなければ)下のような画面になります。

f:id:tsubaki_t1:20160922183644j:plain

AndroidiOS向け、その他諸々も一気に入ります。別プラットフォームで作るときにはSwitchPlatformすればよいので楽です

f:id:tsubaki_t1:20160924200404j:plain

 マーカーを作る

ARマーカーとして反応させるマーカーを作ります。

マーカーの作成には、ダウンロードし解凍したパッケージのbinフォルダ以下にあるgenTexDataを使用します。

f:id:tsubaki_t1:20160924184103j:plain

ターミナルを開き、 genTexData.exe "jpg画像のパス" を指定、あと幾つか質問に解答していけば、マーカーが作られます。
Macの場合はターミナルで上記の作業を行います。(その場合はexeでは無いので注意)

f:id:tsubaki_t1:20160924184746j:plain

マーカーの作成が完了すると、画像と同じフォルダに(画像名).fset、(画像名).fset3、(画像名).isetという拡張子のファイルが作成されます

作成したfset、fset3、isetの拡張子を持つファイルは、StreamingAssetsフォルダに配置します。

f:id:tsubaki_t1:20160924185348j:plain

Unity上でARマーカー表示を行う

次はUnity上でARマーカー表示に関する設定ですが、少し手順の説明が面倒なので、既存のものを変更する形で紹介します。

 

まず、Assets > ARToolKit5-Unity > SimpleNFTScene を開きます。

開いたシーンのARToolKitオブジェクトに設定されているARMarkerコンポーネントのNFT dataset nameを、画像名に変更します。

f:id:tsubaki_t1:20160924190025j:plain

f:id:tsubaki_t1:20160924190201j:plain

 

後は、マーカーに載せるオブジェクトの設定です。

Marker Scene以下にキューブがあるので、ソレを排除、自分の好きなモデルを代わりに配置します。配置したオブジェクトのレイヤーはAR background2を設定します。

配置場所は、マーカーが表示されるので、ソレに従います。

f:id:tsubaki_t1:20160924192745j:plain

後はゲームを再生もしくは実機へ出力し、マーカー画像をカメラの前に翳せば、ARの動作を確認出来ます。

f:id:tsubaki_t1:20160924200935j:plain

もし自分でセッティングを最初からやりたい場合、下の手順で出来ると思います(多分)

  1. ARToolKitオブジェクトを作成し、AR ControllerARMarkerコンポーネントを設定
  2. ARMarkermarkerTagを任意の文字列に設定。同時にTypeをNFTに設定しNFT dataset nameをマーカー名に設定
  3. Scene rootオブジェクトを作成し、AR Originコンポーネントを設定
  4. Scene Rootの子としてCameraオブジェクトとDirectional Lightオブジェクトを配置
  5. CameraCulling MaskをAR background以外に設定
  6. Scene Root以下にMarker sceneオブジェクトを作成し、AR Tracked Objectコンポーネントを設定。marker tagARMarkerに設定したものと一致するように記述。
  7. Marker scene以下に任意のモデルを配置。モデルの所属するレイヤーはCameraCulling Maskに設定したものと同じものにする

こんなもん。

Tips

もしマーカーの範囲が小さすぎたり大きすぎたりする場合、ARMarkerのNFT marker scalefactorを大きくすると、何らかの操作後に大きくなります。

f:id:tsubaki_t1:20160924193145j:plain

 

また、同梱されているMaskシェーダーを使うと、モデルの億にある奴を透明にするアレが出来るので、マーカーの中からコンニチワが出来ます。

f:id:tsubaki_t1:20160924195512j:plain

 

感想

何となく面倒な手順が必要かと思っていましたが、実際には割と簡単でした。

ただファーストインプレッションとしては、vuforiaと比較して認識精度が今ひとつ(ブレる、認識しない)な印象があります。ただ、そのあたりは設定もしくはマーカーの質によって大きく変わるかもしれません。
もしくはNFTではなく古き良きマーカーを使った場合とか。