土屋つかさの技術ブログは今か無しか

土屋つかさが主にプログラミングについて語るブログです。

ミップマップレベルごとに個別のテクスチャを設定したdds形式ファイルを作成する方法

 以前ミップマップについて記事を書いた時、いつか自分でもミップマップレベルごとに個別のテクスチャを設定したデータを作るかもとふんわり書きました。
someiyoshino.info
 ただ、この時は「そうは言ってもそういうテクスチャが必要になることなんて普通無いよな」と思っていたのですが、今回検証作業中に「そういうテクスチャ」が必要になりまして、方法を探しました。

 あらかじめ書いておきますと、「そういうテクスチャ」を作る需要って基本的にプロユースの筈で、その場合はOPTPix*1やNVidiaのPhotoShopプラグイン*2を使えば解決するのかなと思います。今回は無料の「DirectX Texture Tool」を使う方法です。

 DirectX Texture ToolはDirectX SDKに同梱されてるGUIツールで、直感的に作業ができて大変助かりました。ただ、導入までに結構ハマったので、その辺をまとめておきます。

※注意:以下の作業を進めると「一時的にUnityが起動しなくなる」という恐ろしい事態になることがあるので、最後まで読んだ上で、作業については自己責任でお願いします。

手順1:DirectX SDKのインストール

 DirectX Texture ToolはDirectX SDKに同梱されているので、まずDirectX SDKをインストールします。下記サイトにある通りに進めると良いです。
qiita.com
 リンク先でも書かれているように、DirectX SDKを単純にインストールすると、途中でインストールが失敗します。あらかじめ"Microsoft Visual C++ 20xx Redistributable XXX"をアンインストールしなければなりません。

手順2:Visual Studioランタイムの再インストール

 手順1でDirectX SDKをインストール後、Unityを起動しようとすると「VCRUNTIME140.dllがないため、プログラムが開始できません」というメッセージが出て、Unityが起動しなくなります。最初見た時すげー焦った。

 ※2020/11/2 補足:これ、別のPCで同じ処理をした時はこのトラブルは起きませんでした。UnityHubのバージョンとかもあったのかな?

 これは、先ほどの手順で"Microsoft Visual C++ 20xx Redistributable XXX"を全部削除したことが原因です。下記サイトを参考にVisual Studioランタイムをインストールします。
www.javadrive.jp
 ちなみに、Unity2019.4を単体で再インストールしてもこの問題は解消しませんでした。ランタイムを再度インストールしたのち、念のためUnityHubも再インストールし、さらにUnityを単体で再インストールした結果、問題なくUnity起動しました(UnityHub/Unityの再インストールが必要だったのかどうかは不明です。雰囲気としては必要なさそう)。

DirectX Texture Toolでカスタムミップマップテクスチャを作る

 DirectX SDKのインストール後、スタートメニューの"Microsoft DirectX SDK(June 2010)>DirectX Texture Tool(64-Bit)"を選択します。
f:id:t_tutiya:20201103095320p:plain
 メニューの"File>New Texuture..."を選択するとNew Textureウィンドウがポップアップします。テクスチャのサイズと、割り当てるミップマップの数を指定します。MipMap Levelsに4を設定した場合、最上位を含めて4段階のミップマップテクスチャを設定することになります。
f:id:t_tutiya:20201103095332p:plain
 128x128の4段階ミップマップを生成しました。この状態でPageUp/PageDownキーを押すと、処理対象となるミップマップレベルを移動できます。
f:id:t_tutiya:20201103095342p:plainf:id:t_tutiya:20201103095350p:plain
 対象のミップマップレベルに移動して、メニューの"File>Open Onto This Surface..."を選択するとファイルダイアログが表示されるので、それぞれのミップマップレベルに対応するテクスチャを設定します。
f:id:t_tutiya:20201103095359p:plain
 設定が終わったら"File>Save As"でdds形式で出力すれば、カスタムミップマップテクスチャの出来上がりです。dds形式のファイルはUnityが透過的に読み込めます。

【おまけ】ミップマップレベル確認用テクスチャ配布

 検証作業用に作ったテクスチャはお見せできませんが、せっかくなので以前から欲しいと思っていたミップマップの挙動確認用テクスチャを作ってみました。下記からダウンロードできます。

https://main-someiyoshino.ssl-lolipop.jp/file/MipMapLevelSample_t_tutiya.zip

 これまでは海外サイトで配布されていた物を使っていたんですが(冒頭の記事リンク経由でたどれます)、なぜか「1024」と書かれたテクスチャが512x512だったので、使ってて微妙な気持ちになってたんですよね……w。あと、テクスチャによって描き込まれている文字の大きさが違うのも気になっていました。

 今回作成したのは4096/2048/1024/512/256/128/64/32/16/8の10段階のミップマップレベルで構成されたテクスチャです。最近では4096x4096のテクスチャも使うことがあるようなのでこのサイズにしました(オリジナルはベースのサイズが512x512)。
 また、各テクスチャにはサイズを示す数字が描画されています。この数字は全て64x64のサイズで書いてあるので*3、これもブレンド時のガイドになるんじゃないかと思います。

 以下サンプル。Cubeにテクスチャを貼ってカメラを徐々に遠ざけています。各テクスチャの色はオリジナルに多少合わせています。思った以上に良く出来てて我ながら満足度高い。
f:id:t_tutiya:20201103095413p:plain
f:id:t_tutiya:20201103095425p:plain
f:id:t_tutiya:20201103095435p:plain
 線を引いてみました。下図の赤い四角は、どれも同じ面積という事になります。
f:id:t_tutiya:20201103102904p:plain
 参考までに、4096のテクスチャのみだと下図のようになります。こちらはUnityがミップマップを自動生成した物。
f:id:t_tutiya:20201103103653p:plain
 こちらはミップマップの自動性生成をオフにした物。奥の方でテクスチャが潰れてモアレが発生しているのがわかります。
f:id:t_tutiya:20201103103738p:plain

余談

 今回はdds形式ファイルを作る必要があったため、上記の手順にたどり着くまでにやたら苦労したのですが、Unity上で完結していい場合は、Unity上でテクスチャを結合して同様のデータを作ることができます。これもいずれ記事にしたい気持ち。

*1:ゲーム開発会社ならほぼ100%使っているであろうプロユースツール群。個人で使うにはライセンス料がかなり高い気がする(知らない)

*2:プラグイン自体は無料だろうけどPhotoShopが高い

*3:32/16/8は例外