【VRChat】テクスチャのインポート設定によるVRAM最適化

[Developer Update](https://ask.vrchat.com/t/developer-update-16-february-2023/16474#avatar-performance-stat-changes-11)によると、アバターのパフォーマンスランクにVRAM容量が追加されるようです。これは[Twitterで雑につぶやいていた](https://twitter.com/lil_xyzw/status/1573205128064421888)話について備忘録ついでにまとめたほうが良いなということでまとめました。この記事はアバターでの話を中心に書いていますが、ワールドについても当てはまる部分が多いです。長々と書いているので要点だけ知りたい場合は[まとめ](#まとめ)だけご覧ください。

# テクスチャのインポート設定

## 解像度を下げる
当たり前ですがここで挙げているテクニックの中で効果が最も大きいです。**解像度が1段階上がるだけで容量が約4倍になる**のでできる限り小さくしておきたいです。以下は解像度のギリギリを攻めるときの私なりの考え方です。
- 解像度は基本的に2048以下にする
- 靴など目立たない部分は更に攻めて512などにする
- マスクテクスチャは128のようなかなり低い解像度まで下げても気にならない場合も多い
- MatCapは使用している部位によっては32のような極端に低い解像度でも良い場合がある
- 「解像度を下げたらノイズが気になる……」という場合はインポート設定を`High Quality`にしてみる（後述）

Unityでドアップにすると解像度が気になることがありますが、**密着した状態で舐め回すようにテクスチャを見てもらう**機会はあまりないです（特に負荷を気にすべき人の多いインスタンスにおいて）。容量4倍で綺麗にするか人のPCに配慮するか、どちらを優先するかはアバターの使用場面を考慮しつつしっかり吟味しましょう。

## インポート設定を`High Quality`にしてみる
`Normal Quality`だとRチャンネルは特に劣化しやすいので肌のテクスチャなんかはかなり影響が大きいです。クオリティが上がるぶん容量が大きくなる場合もあるため以下の点に注意が必要です。
- テクスチャに透明度を含まない場合、`High Quality`にすると容量が2倍になる
- テクスチャに透明度を含む場合は`High Quality`にしても容量が変わらない（表情や衣装のテクスチャが当てはまりやすい）
- `Normal Quality`と`High Quality`で同じ容量の場合、`Normal Quality`の方がビルド時の圧縮が効きやすい

## 頂点シェーダーで使うテクスチャはMipMapオフで良い
アウトラインの太さやファーの向きの制御など頂点の操作に関わるテクスチャがこれに当てはまります。1枚あたり約33％の削減になるため**容赦なくオフにしましょう**。なお、ピクセルシェーダーで使うテクスチャでMipMapを切るとジラジラの原因になるため基本的に**オンのまま**が良いです。

## Crunch CompressionはVRAM最適化においては無意味
Unity上では容量が目に見えて小さくなってウハウハになれるのですが、これはzip圧縮みたいな感じで実際に使うときには展開する必要があります。**ロード時の展開で容量が戻るため見た目以上にVRAMを食いつぶす**ことになります。また、アバターの場合はビルド時に`Crunch Compression`とは別の圧縮がかかるのですが、これによって`Crunch Compression`未使用のテクスチャとの容量の差が小さくなります。

ちなみに`Crunch Compression`は展開時に若干負荷があるそうですが、重いなと感じたことはほぼないです。しかし、それを抜きにしてもテクスチャが劣化する上に受けられる恩恵はダウンロードサイズがちょっと小さくなる程度、その上VRAM最適化したアバターは基本的に容量も小さいので個人的には**アバターへの使用は非推奨**です。~~逆にビルド時の圧縮の恩恵を受けられないワールドにおいては`Crunch Compression`を利用した方が良いです。~~
【2023/3/17追記】
[Developer Update - 16 March 2023](https://ask.vrchat.com/t/developer-update-16-march-2023/16950#sdk-warning-improvements-6)によると現在ではワールドにも圧縮がかかっているようです。

# TexTransToolを使う
**もとの素材には手を加えずに**アップロード時にUVとテクスチャを自動で編集する（非破壊編集）ツールとして、[TexTransTool](https://ttt.rs64.net/)というものがあります。このツールの[AtrasTexture](https://ttt.rs64.net/docs/Tutorial/AtlasTexture-Tutorial)という機能を使うことでテクスチャから無駄な領域を減らしVRAM削減を行うことができます。

# それ以外の最適化

## 一部しか使わないテクスチャは使う部分だけ切り抜く
例えば髪留めを付けているアバターの髪留めだけ使うような場合、衣装のテクスチャのうち髪留めの部分しか使わないため**未使用の部分で無駄にメモリを食う**ことになります。画像編集ソフトで髪留めの部分だけ切り抜き、マテリアルのUV設定で切り抜いたテクスチャにピッタリ合うように調整することで無駄をなくすことができます。切り抜く際に四分割や八分割などキリのいい数値のグリッドに合わせて切り抜くとUVの逆算が楽になります。Blenderでの編集が必要になりますが、UVをいじって他テクスチャの隙間にねじ込むのもマテリアル数の削減にもつながるため効果的です。

## マテリアルに残っている無駄なテクスチャを消す
シェーダーを変えた場合は以前設定したテクスチャが内部にそのまま残っていて、これが無駄に容量を大きくする原因になっている場合があります。シェーダーによっては不要なプロパティを削除する機能があるのでそれを使って消しておきましょう。

## 1アバター1衣装
衣装が増えれば増えるだけ衣装に使うテクスチャも増えていきます。アバターに大量の衣装バリエーションがある場合はアップロードが楽になるといったメリットもなくはないですが、ランタイムでのパフォーマンスを考えるとやはり1アバター1衣装がオススメです。これはVRAM最適化以外の面でもそうで、
- アニメーションがブロックされている等で同期がうまくいっていない場合に**自分視点では正常でも他人視点では脱げている**
- 大量の衣装を入れた上でPhysBonesやConstraint等が有効なままだと無駄にパフォーマンスを悪化させる
- 以前はアバターごとにキャリブレーションが必要だったが、今はアバターを変えても保持される

など気にすべき要素に対しメリットが弱くなっているため、（特別な演出意図がある場合等を除いて）1アバター1衣装がオススメです。

# まとめ
- 解像度を下げる（最優先）
- 劣化が気になるならインポート設定を`High Quality`にする
- 頂点操作系のテクスチャはMipMapを切る
- アバターで`Crunch Compression`は非推奨
- 一部しか使っていないテクスチャは必要な部分だけ切り抜く
- マテリアルに残っている無駄なテクスチャは消す
- 1アバター1衣装