MRが楽しい

MRやVRについて学習したことを書き残す

ユニティちゃんのマテリアルのSetPass Callをモデル毎に発生させる

本日はホロ恋子ローポリモデルの負荷試験のおまけ枠です。
ユニティちゃんのマテリアルのSetPass Callをモデル毎に発生させてみます。
前回記事の続きです。
bluebirdofoz.hatenablog.com

モデル増加時のレンダリング負荷

ユニティちゃんのモデル増加時の負荷を確認するため、2体のユニティちゃんのオブジェクトを用意します。
そのままシーンを再生すると、Batches 78、SetPass calls 14 となります。
f:id:bluebirdofoz:20190517092850j:plain

前回、1体辺りのユニティちゃんの負荷を計測したところ、Batches 41、SetPass calls 14 でした。
bluebirdofoz.hatenablog.com

ホロ恋子の拳商事と同様に「同じマテリアルの SetPass Call は統合」されていることが分かります。
更に Batches についてもまとめられているためか期待値の 81 よりも低い値になっています。
(Batches の内、1つはバッファクリアの Batches のため、1 + 40(1体のユニティちゃん) * 2(体) = 81 が期待値になります)

ユニティちゃんのマテリアルをモデル毎に変更する

前回記事ではホロ恋子モデルのマテリアルを動的に変更することで、モデル毎にSetPass Callが発生するようにしました。
ユニティちゃん相当のモデル増加時の負荷も計測するため、ユニティちゃんにも同じ処理を行うスクリプトを作成します。

ホロ恋子モデルとの違い、ユニティちゃんはマテリアルが複数のスキンメッシュ毎に設定されており、かつ、複数のスキンメッシュが同じマテリアルを参照しています。
よって、オブジェクトの子オブジェクトに含まれる Renderer を探査し、同名のマテリアルの変更を共有するスクリプトを作成しました。
・SetTextureChildren.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SetTextureChildren : MonoBehaviour {

    /// <summary>
    /// 起動時処理
    /// </summary>
    void Start () {
        // 自オブジェクトまたは子オブジェクトから Renderer コンポーネントを取得する
        // GetComponentsInChildren は再帰的に探査される
        Component[] renderers;
        renderers = GetComponentsInChildren(typeof(Renderer));

        // 動的に変更したマテリアルは同名のものを共有するため
        // 連想配列でマテリアル名とマテリアルを保持しておく
        Dictionary<string, Material> materialList = new Dictionary<string, Material>();

        if (renderers != null)
        {
            // 取得した Renderer オブジェクトを1つずつ処理する
            foreach (Renderer renderer in renderers)
            {
                // マテリアルとマテリアル名を取得する
                Material setMaterial = renderer.material;
                string materialName = setMaterial.name;
                // 既に同名のマテリアルを動的に変更したか
                if (materialList.ContainsKey(materialName))
                {
                    // 既に動的に変更した同名のマテリアルがあれば、それを再設定する
                    renderer.material = materialList[materialName];
                }
                else
                {
                    // 未編集のマテリアルであれば、カラーを再設定することでマテリアルの共有を切る
                    Color setColor = setMaterial.color;
                    setMaterial.color = setColor;
                    // 変更後のマテリアルは同じモデル内の同名マテリアルで共有するため
                    // 連装配列にマテリアル名と一緒に保持しておく
                    materialList.Add(materialName, setMaterial);
                }
            }
        }
    }
}

ユニティちゃんのオブジェクトに本スクリプトを以下のようにアタッチしました。
f:id:bluebirdofoz:20190517092916j:plain

この状態でシーンを再生してみると……。
f:id:bluebirdofoz:20190517092929j:plain
Batches 81、SetPass calls 27 となりました。想定通りの数値です。

Blenderのログをpythonコードで確認する

本日は Blneder の調査枠です。
Blender で操作したログを確認する方法について記事にします。

ログウィンドウの表示

方法は簡単です。メニューがある[情報]ウィンドウの下部をドラッグして下げるだけです。
f:id:bluebirdofoz:20190516092933j:plain

これでログの表示欄が見えるようになりました。
f:id:bluebirdofoz:20190516092942j:plain

操作の実行

試しに、実際に操作を行ってみます。
オブジェクトから[オブジェクトの複製]を実行してみます。
f:id:bluebirdofoz:20190516092952j:plain

[オブジェクトの複製]を実行すると、オブジェクトを複製した後、ドラッグ操作で複製オブジェクトの配置場所を指定できます。
[Xキー] -> [4キー] を押下して、X軸方向に 4 移動した位置に複製オブジェクトを配置しました。
f:id:bluebirdofoz:20190516093001j:plain

[Enterキー]で操作を完了すると……。
f:id:bluebirdofoz:20190516093011j:plain
[オブジェクトの複製]操作がpythonコードでログ出力されました。
bpy.ops.object.duplicate_move()の操作関数だけでなく、その後の軸移動などの引数パラメータも表示されています。

右クリックで選択 -> [Ctrl + Cキー] でコードをコピーすることもできるので、pythonスクリプトを作成する参考にできます。
f:id:bluebirdofoz:20190516093019j:plain

ホロ恋子ローポリモデルの負荷試験を行う その2(SetPass calls の発生検証)

本日はホロ恋子ローポリモデルの負荷試験です。
ホロ恋子ローポリモデルの表示数を増やしてレンダリング統計ウィンドウで確認してみます。
前回記事の続きです。
bluebirdofoz.hatenablog.com

表示モデルを増やす

早速、シーンにモデルを25体追加してみました。
f:id:bluebirdofoz:20190515093056j:plain

この状態でシーンを再生し、まずはレンダリング統計ウィンドウで確認してみます。
すると以下の通り、Batches が 26、SetPass calls が 2 となりました。
f:id:bluebirdofoz:20190515093108j:plain

Batches の増加は順当ですが、SetPass calls が増えていません。
これはレンダリング統計ウィンドウの調査で記事にした通り、「同じマテリアルの SetPass Call は統合」されるためです。

マテリアルの動的更新によるSetPass callsの発生

単純にアプリとして利用する限りは最適化されるのは良いことですが、モデルの負荷試験としては適切とは言えません。
SetPass calls がモデル毎に呼ばれるようにしてみます。

Unity の設定による変更方法が不明だったので、スクリプトを追加して個別に SetPass calls を発生させることにしました。
以下のような起動時にマテリアルへテクスチャを再設定するスクリプトを作成しました。
・SetTexture.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SetTexture : MonoBehaviour {
    /// <summary>
    /// マテリアルに設定するテクスチャ
    /// </summary>
    public Texture setTexture;
    /// <summary>
    /// 参照マテリアル
    /// </summary>
    private Material p_Material = null;

    /// <summary>
    /// 起動時処理
    /// </summary>
    void Start () {
        // コンポーネントがアタッチされたオブジェクトのマテリアルを取得する
        Renderer renderer = GetComponent<Renderer>();
        p_Material = renderer.material;
        // メインテクスチャを設定する
        p_Material.SetTexture("Texture", setTexture);
    }
}

起動時にマテリアルが動的に更新されるため、SetPass calls が統合されなくなるはずです。
試しに1体のモデルにスクリプトをアタッチしてみます。
f:id:bluebirdofoz:20190515093126j:plain

この状態でシーンを再生してみると……。
SetPass calls が 3 になりました。マテリアルを動的に変更されたモデルの SetPass calls が分割されています。
f:id:bluebirdofoz:20190515093137j:plain

モデルを Prefab 化して全てのモデルに SetTexture スクリプトを反映してみました。
この状態でシーンを再生すると……。
f:id:bluebirdofoz:20190515093148j:plain
SetPass calls も 26 になりました。マテリアルの動的更新によって SetPass calls が個別に発生したことが分かります。

なお、逆にマテリアルを共有したまま更新したい場合は Renderer.sharedMaterial でマテリアルを参照するとよいそうです。
docs.unity3d.com

プレハブの動的追加によるSetPass callsの発生の検証

マテリアルの動的更新で SetPass calls は個別に発生することが分かりました。
しかし、この方法だとモデルに余計なスクリプトが追加されてしまいますし、テクスチャの多いモデルは設定が大変です。

モデルをそのままに、ゲームオブジェクト自体を動的に追加した場合は SetPass Call は個別に発生するのか検証してみます。
以下のような起動時に prefab を動的に追加するスクリプトを作成しました。
・InstantiatePrefab.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InstantiatePrefab : MonoBehaviour {
    /// <summary>
    /// 動的に追加するプレハブ
    /// </summary>
    public GameObject setPrefab;

	// Use this for initialization
	void Start () {
        // 子オブジェクトとしてプレハブを生成
        Instantiate(setPrefab, transform);
    }
}

試しにスクリプトをアタッチしたゲームオブジェクトをシーンに配置します。
ホロ恋子ローポリモデルの prefab を引数に設定します。
f:id:bluebirdofoz:20190515093236j:plain

シーンを再生すると、Prefab がシーン上に動的に追加されました。
f:id:bluebirdofoz:20190515093247j:plain

こちらも同じく25個の同様のゲームオブジェクトを配置し、シーンを再生してみます。
するとこちらは SetPass calls が 2 になりました。
f:id:bluebirdofoz:20190515093257j:plain
マテリアルを動的に変更しない限り、同じ Prefab のマテリアルの SetPass Call は統合されることが分かります。

ホロ恋子ローポリモデルの負荷試験を行う その1(レンダリング統計ウィンドウでの比較)

本日はホロ恋子ローポリモデルの負荷試験です。
キャラクターモデルの負荷をレンダリング統計ウィンドウで確認し、比較してみます。
以下の記事の続きです。
bluebirdofoz.hatenablog.com

比較するモデル

今回はユニティちゃんとホロ恋子モデルを比較して見ます。
シーンの環境はレンダリングへの影響を抑えるため、背景は[Solid Color]とし、影は[No Shadows]で無効化しています。
f:id:bluebirdofoz:20190514091205j:plain

ホロ恋子モデルは以下の特徴があるため、ユニティちゃんより負荷が少ない結果が期待できます。
・全オブジェクトを結合したことによるスキンメッシュの統合
・ポリゴン数の削減(ホロ恋子モデル:約2,000ポリゴン、ユニティちゃん:約16,000ポリゴン)
・マテリアルを1つのUnlit/Textureマテリアルに統合
・Humanoidリグに必要なボーンオブジェクトのみ

ユニティちゃんモデルの表示結果

ユニティちゃんモデルをカメラから2mのところに表示してみました。
なお、スクリプトによる負荷の変化を防ぐため、Models/unitychan.fbx ファイルを利用しています。
f:id:bluebirdofoz:20190514091248j:plain
Batchs は 41。SetPass calls は 14 となりました。

ホロ恋子モデルの表示結果

同じくホロ恋子モデルをカメラから2mのところに表示してみました。
f:id:bluebirdofoz:20190514091258j:plain
Batchs は 2。SetPass calls は 2 となりました。

比較結果

比較結果は以下の通りです。

モデルユニティちゃんホロ恋子
Batches412
Saved by batching00
Tris31.5k2.0k
Verts26.2k1.6k
SetPass calls142
Shadow casters00
Visible skinned meshes191

かなり有意な差が発生することが分かりました。
ユニティちゃんモデルはオブジェクトの分割数が多いため、スキンメッシュの数が多く、またマテリアルも細かく分割されているため、1体だけでも Batches の数が 41 と非常に多くなっていることが分かります。
一方、ホロ恋子モデルの方はオブジェクトやマテリアルの結合を行ったため、スキンメッシュの数が少なく、Batches は最低数の 2 となっています。
(それぞれ Batches の数値の内、1つはバッファクリアのバッチングのため 2 が最低数になります)

FPSはPC上での確認かつ、1体のみの表示のため、差は発生していません。
しかし複数体のモデルを表示したときの負荷軽減は期待できそうです。

SDユニティちゃんの場合

ついでにSDユニティちゃんのレンダリング負荷も確認してみました。
f:id:bluebirdofoz:20190514091346j:plain
Batchs は 25。SetPass calls は 11 となりました。
頭身が低いため、頂点数は減っているものの、スキンメッシュの分割やマテリアルの分割が行われているため、それなりの負荷が発生することが分かります。

ローポリユニティちゃんの場合

更にローポリユニティちゃんのレンダリング負荷も確認してみました。
f:id:bluebirdofoz:20190514091405j:plain
Batchs は 2。SetPass calls は 2 となりました。
ホロ恋子モデルと同じで、最低数の Batches と SetPass calls となります。
実際、全てのスキンメッシュとマテリアルが統合されており、シェーダも Unlit/Texture が用いられるなど、ホロ恋子モデルとモデルの構成が同じです。

GitHubの利用手順(Unityプロジェクトの登録)

本日は GitHub の利用手順です。
本記事では GitHub に Unity プロジェクトを保存する手順を記事にします。
前回記事の続きです。
bluebirdofoz.hatenablog.com

.gitignoreの設定

Unity プロジェクトを登録するリポジトリを作成する場合、リポジトリ作成の設定で[Add .gitignore]に[Unity]を設定します。
f:id:bluebirdofoz:20190513082041j:plain

[Add .gitignore]に[Unity]を設定してリポジトリを作成すると、.gitignore ファイルがリポジトリに生成されます。
f:id:bluebirdofoz:20190513082052j:plain

.gitignore ファイルの内容は以下の通りです。
Unity プロジェクトにおいて、バージョン管理が不要なファイルを無視するための条件が設定されています。

[Ll]ibrary/
[Tt]emp/
[Oo]bj/
[Bb]uild/
[Bb]uilds/
Assets/AssetStoreTools*

# Visual Studio cache directory
.vs/

# Autogenerated VS/MD/Consulo solution and project files
ExportedObj/
.consulo/
*.csproj
*.unityproj
*.sln
*.suo
*.tmp
*.user
*.userprefs
*.pidb
*.booproj
*.svd
*.pdb
*.opendb

# Unity3D generated meta files
*.pidb.meta
*.pdb.meta

# Unity3D Generated File On Crash Reports
sysinfo.txt

# Builds
*.apk
*.unitypackage

Unityプロジェクトを登録

試しに、実際に Unity プロジェクトを登録してみます。
前回作成したローカルリポジトリに新規の Unity プロジェクトを作成します。
f:id:bluebirdofoz:20190513082104j:plain

以下の通り、プロジェクトをビルドまで実施しました。
UWP 向けビルドを実行したので、新たに UWP フォルダと、アプリの出力先として作成した App フォルダが追加されています。
f:id:bluebirdofoz:20190513082121j:plain

これらのビルドファイルは GitHub に含めたくないので .gitignore ファイルに更に以下の条件を追加しました。

App/
UWP/

Unity プロジェクトのフォルダを右クリックして、TortoiseGit -> 追加 で登録対象のファイルを追加します。
f:id:bluebirdofoz:20190513082132j:plain

登録対象のファイルが表示されます。
.gitignore で指定したファイルは自動的に除外されています。
f:id:bluebirdofoz:20190513082144j:plain

ファイルの追加を行ったら、右クリックから Git コミット で変更をコミットします。
f:id:bluebirdofoz:20190513082154j:plain

最後にローカルリポジトリの変更を GitHubリポジトリに反映します。
右クリックから TortoiseGit -> プッシュ を実行します。
f:id:bluebirdofoz:20190513082221j:plain

宛先にはリモートの[origin]を指定します。
f:id:bluebirdofoz:20190513082203j:plain

これで登録は完了です。GitHubリポジトリページを確認します。
登録ファイルがアップロードされ、Commit が1つ増えていることが確認できます。
f:id:bluebirdofoz:20190513082232j:plain

GitHubの利用手順(リポジトリの作成)

本日は GitHub の利用手順です。
本記事では GitHubリポジトリ作成の手順を記事にします。
前回記事の続きです。
bluebirdofoz.hatenablog.com

リポジトリの作成

GitHubのページから前回登録したアカウントでサインインを行います。
github.com
f:id:bluebirdofoz:20190512213805j:plain

マイページが開いたら、右上の[+]ボタンをクリックしてプルダウンを開きます。
[New repository]をクリックします。
f:id:bluebirdofoz:20190512213818j:plain

リポジトリの作成ページが開きます。
以下の各項目を入力します。

リポジトリ名:(アカウント名)/(リポジトリ名)の形で名前を入力する(必須)。
説明文:リポジトリの説明文を入力する。
公開権限:Public(公開)かPrivate(非公開)を選択する。
Initialize this repository with a README:リポジトリ作成時にREADMEファイルを自動生成する。
Add .gitignore:無視するファイルの種別を指定する。
Add a license:リポジトリのライセンスを指定する。

f:id:bluebirdofoz:20190512213829j:plain

2019年から無料プランでも Private リポジトリが利用可能となっています。
ただし無料プランの場合登録可能な共同編集者は3名までです。
github.blog

入力を行ったら[Create repository]を実行します。
f:id:bluebirdofoz:20190512213912j:plain

これでリポジトリが作成されました。
f:id:bluebirdofoz:20190512213852j:plain

ローカルリポジトリの作成

では実際に作成したリポジトリにプロジェクトを登録してみます。
初めにPCの任意のフォルダにリポジトリをクローンしてローカルリポジトリを作成します。

ここでは Git の操作に TortiseGit のツールを利用します。
TortoiseGit のインストール手順は以下を参照ください。
bluebirdofoz.hatenablog.com

リポジトリページの[Clone or download]を開き、[Clone wiht HTTPS]のURLを取得します。
f:id:bluebirdofoz:20190512213952j:plain

任意のフォルダで右クリックを行い、[Gitクローン(複製)]を実行します。
f:id:bluebirdofoz:20190512214002j:plain

[URL:]に再帰ほど取得したリポジトリのURLを入力します。
クローン先のディレクトリを確認し、[OK]をクリックします。
f:id:bluebirdofoz:20190512214011j:plain

GitHub へのサインイン画面が開きます。
アカウント名とパスワードを入力して、[Login]をクリックします。
f:id:bluebirdofoz:20190512214021j:plain

次にリポジトリを編集するアカウントの設定画面が表示されます。
Private リポジトリで共同編集者を設定していない場合、対象のリポジトリを編集できるのはリポジトリを作成したアカウントのみです。
GitHub へサインインしたときと同じアカウント名とパスワードを入力します。
f:id:bluebirdofoz:20190512214037j:plain

これで任意のディレクトリにリポジトリがクローンされました。
f:id:bluebirdofoz:20190512214049j:plain

アプリパッケージでhololensにアプリをインストールする(RS5版)

本日は hololens の技術調査枠です。
以下の記事の RS5 版の DevicePortal での手順をまとめます。
bluebirdofoz.hatenablog.com

HoloLens の DevicePortal を開きます。
RS5 では[Views]配下に[Apps]があります。[Views]を開き、[Apps]をクリックします。
f:id:bluebirdofoz:20190511094144j:plain

[Apps]画面を開いたら[Deploy Apps]パネルにある[ファイルを選択]ボタンをクリックします。
f:id:bluebirdofoz:20190511094153j:plain

ファイル選択ダイアログが開きます。インストールする appxbundle ファイルを選択します。
f:id:bluebirdofoz:20190511094202j:plain

フレームワークのパッケージが別にある場合は[Allow me to select framework packages]のチェックを入れます。
[Next](またはチェックを入れていない場合は[Install])ボタンをクリックします。
f:id:bluebirdofoz:20190511094211j:plain

フレームワークのチェックを入れた場合、依存ファイルの選択画面が表示されます。
[ファイルを選択]ボタンをクリックします。
f:id:bluebirdofoz:20190511094223j:plain

ファイル選択ダイアログが開きます。依存するフレームワークの appx ファイルを選択します。
依存ファイルが複数ある場合は、ボタン操作を繰り返して複数のファイルを選択します。
f:id:bluebirdofoz:20190511094232j:plain

依存ファイルを全て選択したら[Install]ボタンをクリックします。
f:id:bluebirdofoz:20190511094241j:plain

インストールが開始されます。プログレスバーが完了するまで待機します。
f:id:bluebirdofoz:20190511094249j:plain

インストールが成功すると、Installation Complete の表示がされます。
既にフレームワークがインストール済みであった場合、フレームワークのインストールは自動でスキップされます。
f:id:bluebirdofoz:20190511094258j:plain