Slide 1

Slide 1 text

背景メッシュの結合による 最適化に向けたトライ&エラー 村上克弥 ファイトリーグ事業部 クライアント開発グループ 2018/07/25

Slide 2

Slide 2 text

自己紹介 所属 株式会社ミクシィ XFLAG スタジオ ファイトリーグ事業部 クライアント開発グループ 経歴 2013年 東京の某社に入社 ・K社の有名なIPとか ・S社の有名なIPを扱ったタイトルとか 2017年 ミクシィ入社 ・ファイトリーグでクライアント開発やってます ・実装とかツール作りとか色々やってます。 その他 褒められたい 名前:村上克弥

Slide 3

Slide 3 text

突然ですが うちのプロジェクト 背景のGameObject数がそこそこあるんです。

Slide 4

Slide 4 text

でも、デザイナさんに罪はないので メッシュ結合ツールを作りました。

Slide 5

Slide 5 text

意外と大変でした。 頑張ったんで、褒めてほしいです。 聞いてください。

Slide 6

Slide 6 text

要件 ・背景メッシュを結合し、GameObjectを減らす ・本来の見た目を問題ない範囲で維持する ・それによってパフォーマンスを低下させない ・あわよくばドローコールを減らす ・レンダラーパラメーターの異なるものを結合しない ・アニメーションするメッシュは結合しない ・スキンメッシュは結合しない ・参照されているゲームオブジェクトは結合しない ・褒めてほしい

Slide 7

Slide 7 text

要件 ・背景メッシュを結合し、GameObjectを減らす ・本来の見た目を問題ない範囲で維持する ・それによってパフォーマンスを低下させない ・あわよくばドローコールを減らす ・レンダラーパラメーターの異なるものを結合しない ・アニメーションするメッシュは結合しない ・スキンメッシュは結合しない ・参照されているゲームオブジェクトは結合しない ・褒めてほしい ↑この辺は大変じゃなかったんで、語りません。

Slide 8

Slide 8 text

↓これですが。 要件 ・本来の見た目を問題ない範囲で維持する

Slide 9

Slide 9 text

要件 今回サンプルに選んだのは、 で使用している背景

Slide 10

Slide 10 text

要件 ゲームオブジェクト数はこれくらい。

Slide 11

Slide 11 text

では、やっていきます

Slide 12

Slide 12 text

CombineMeshes まず最初に思いつくのはこれです。

Slide 13

Slide 13 text

CombineMeshes 理想では、こんなふうに結合してくれるはずです。 やってみました。

Slide 14

Slide 14 text

駄目です。

Slide 15

Slide 15 text

CombineMeshes このAPIは、SubMeshがある場合 サブメッシュごとに結合しなければなりません。

Slide 16

Slide 16 text

CombineMeshes 一度、別のメッシュに分離するので、 サブメッシュ間の共有頂点が複製されてしまい、 頂点数が増えます。

Slide 17

Slide 17 text

CombineMeshes(を手作り) 幸い、経験上、Meshクラスの構造には 覚えがありました。 マテリアルの情報からサブメッシュを振り分け、 まとめて一回でメッシュ結合する仕組みを作ります。

Slide 18

Slide 18 text

CombineMeshes(を手作り) 出来ました。 ※ライトマップは焼いてません

Slide 19

Slide 19 text

CombineMeshes(を手作り) GameObject数も激減。

Slide 20

Slide 20 text

CombineMeshes(を手作り) あとは、ライトマップを焼いて、 左の見た目になれば成功です。 やってみました。

Slide 21

Slide 21 text

駄目です。

Slide 22

Slide 22 text

CombineMeshes(を手作り) やってみた結果

Slide 23

Slide 23 text

CombineMeshes(を手作り)

Slide 24

Slide 24 text

CombineMeshes(を手作り) 理想 現実

Slide 25

Slide 25 text

CombineMeshes(を手作り) 世紀末

Slide 26

Slide 26 text

CombineMeshes(を手作り) 謎の荒れの原因は、ライトマップ用のUVが作られていな かったことです。 Unityではuv2をライトマップ用UVとして使うので uv2を生成する必要があります。

Slide 27

Slide 27 text

SecondaryUVを生成 こんな関数を見つけました。 実際に使ってみました。

Slide 28

Slide 28 text

SecondaryUVを生成 お!いいかんじ!

Slide 29

Slide 29 text

駄目です。

Slide 30

Slide 30 text

SecondaryUVを生成 ライトマップテクスチャがページングされていました。 このままでは、ドローコール増加につながるため パフォーマンスが低下します。

Slide 31

Slide 31 text

SecondaryUVを生成 原因は、メッシュを結合する際 MeshRendererの「Scale In Lightmap」を 考慮していないせいです。 そのせいで、等倍のライトマップが生成されています。

Slide 32

Slide 32 text

「Scale In Lightmap」を逆算 結合前の全メッシュのライトマップ総面積を足して、 その平方を取れば、 同じ面積でライトマップを生成できるはずです。 問題はその計算式です。

Slide 33

Slide 33 text

「Scale In Lightmap」を逆算

Slide 34

Slide 34 text

ありました。 「Scale In Lightmap」を逆算

Slide 35

Slide 35 text

この辺はリフレクションで呼び出します。 「Scale In Lightmap」を逆算

Slide 36

Slide 36 text

「Scale In Lightmap」を逆算 そして出来た「Scale In Lightmap」です。

Slide 37

Slide 37 text

ぱっとみ良さげに見えるし、 ライトマップテクスチャも1枚です。 これならいけるのでは? 「Scale In Lightmap」を逆算

Slide 38

Slide 38 text

駄目です。

Slide 39

Slide 39 text

解像度の低い部分が出てしまいます。 これではデザイナさんの調整が死にます。 結合前 結合後 「Scale In Lightmap」を逆算

Slide 40

Slide 40 text

アプローチを変えました。 「Scale In Lightmap」を逆算

Slide 41

Slide 41 text

結合前にライトマップを焼く uv2にライトマップのUVが入っているので 結合前のライトマップテクスチャを 使うことができるはずです。

Slide 42

Slide 42 text

結合前にライトマップを焼く PropertyBlockでテクスチャを適用するコンポーネントを作成。 lightmapScaleOffsetからUVを再計算。 シェーダーキーワード「LIGHTMAP_ON」を適用。

Slide 43

Slide 43 text

結合前にライトマップを焼く これで今度こそいけるはずです!

Slide 44

Slide 44 text

駄目です。

Slide 45

Slide 45 text

結合前にライトマップを焼く ライトマップは適用されてるけど めっちゃ明るくなった…。

Slide 46

Slide 46 text

結合前にライトマップを焼く FrameDebuggerで見てみると

Slide 47

Slide 47 text

結合前にライトマップを焼く 誰やねんお前

Slide 48

Slide 48 text

LIGHTPROBE_SHをスキップ 「LIGHTPROBE_SH」は Unityによって、強制的に設定されます。 Lightmap焼き込み済みのオブジェクトは 「LIGHTPROBE_SH」が除外されるようです。 なので 「#pragma skip_variants LIGHTPROBE_SH」 を記述したシェーダーを作成します。 (#pragmaは#ifdefで弾けない…仕様?) 結合時にシェーダーを差し替えることで、 対応します。

Slide 49

Slide 49 text

LIGHTPROBE_SHをスキップ 結果

Slide 50

Slide 50 text

LIGHTPROBE_SHをスキップ

Slide 51

Slide 51 text

LIGHTPROBE_SHをスキップ 結合前 結合後 見た目よし…。

Slide 52

Slide 52 text

LIGHTPROBE_SHをスキップ 結合前 結合後 諸々、数値よし…。

Slide 53

Slide 53 text

OKです!

Slide 54

Slide 54 text

まとめ

Slide 55

Slide 55 text

まとめ ライトマップの解決は大変。 褒めてほしい。