すぎしーのXRと3DCG

主にXR, Unity, 3DCG系の記事を投稿していきます。

【Unity】シーンからCubemapを作成してpngファイルで出力するツールを作ってみた

f:id:tsgcpp:20200701205557p:plain

2021/06/19追記

諸々更新してツールの見た目が変わっています。
以下の記事は v0.0.3 に関する記事となっています。

概要

Unityで作成したシーンからCubemapを作成して、pngファイルとして出力するツールを作成したので紹介します。
Camera.RenderToCubemapを使用することでCubemap自体は作成できますが、そのCubemapをテクスチャファイルに出力するツールが見当たらなかったので作ってみました。
また、作成の過程で気になった点も併せて共有します。

記事の最後にgithubのリンクを記載します。

環境

前知識

テクスチャ形式

  • 公式ドキュメントのCubemapsに記載されているCreating Cubemaps from Texturesで解説されているテクスチャに準拠して作成します
  • 現時点では縦または横に並べた形式のみをサポート

f:id:tsgcpp:20200701192521p:plain
テクスチャ形式 (Cubemapsページより引用)

Texture2D.SetPixels

Cubemap.GetPixels

  • Cubemap.GetPixels
  • 指定したfaceに対応するテクスチャのピクセル配列をゲットするメソッド
  • ピクセルの順番は右上から左下
    • Texture2D.SetPixelsとは順番が異なるため要注意
    • The returned array is a flattened 2D array, where pixels are laid out right to left, top to bottom より

Camera.RenderToCubemap

  • Camera.RenderToCubemap
  • Cameraオブジェクトのpositionを中心としてCubemapを作成するメソッド

実装方針

  • タブから作成を実行
    • MenuItemを使用
  • テクスチャサイズは可変
    • Wizardにpublic int widthを追加
  • テクスチャ形式を指定可能
    • Wizardにpublic FileType fileTypeを追加
  • Cameraの位置を指定可能
    • Wizardにpublic Transform renderFromPositionを追加
  • ファイル出力先を指定可能
    • EditorUtility.SaveFilePanelを使用

実装までの流れ

CubemapFileGeneratorWizardの作成

  • EditorツールにするためScriptableWizardCubemapFileGeneratorWizard`を継承したクラスCubemapFileGeneratorWizardを作成
    • 基本的にはCamera.RenderToCubemapRenderCubemapWizardを参考に作成
    • ScriptableWizardの詳細については割愛

テクスチャ形式に合わせたConverterを作成

注意点としてVerticalPng(テクスチャを縦に並べる形式)の場合はSetPixelsを実施する順番を気を付けてください。
Texture2D.SetPixelsは画像の左下が原点なので、-Z, +Z, -Y, +Y, -X, +Xの順番(下から上)でセットするように実装しています。

Texture2DとCubemapの差異を補正するSetPixelsメソッドを作成

  • 「前知識」で記載しましたが、Texture2DとCubemapには差異があるため、それを補正するメソッドを作成
  • Texture2DExtensions
    • 今回はTexture2Dの拡張として実装
Color[] pixels = cubemap.GetPixels(face);

// Cubemap.GetPixelsは右上から左下の順番のため、
// SetPixelsに左下から右上の順番に合わせて反転させる
System.Array.Reverse(pixels);
for (int i = 0; i < blockWidth; ++i) {
    System.Array.Reverse(pixels, i * blockHeight, blockWidth);
}

texture.SetPixels(x, y, blockWidth, blockHeight, pixels);

ツールの使用方法

ツールの起動

f:id:tsgcpp:20200701204256j:plain

ツールの設定

  • 以下は設定例
    • サイズは512x512
    • テクスチャは横に並べる

f:id:tsgcpp:20200701201152j:plain

実行結果

対象のシーン

  • UniversalRPのサンプルシーンを使用

f:id:tsgcpp:20200701201112j:plain

生成されたテクスチャ

f:id:tsgcpp:20200701201253p:plain

f:id:tsgcpp:20200701202053j:plain
TextureShape: Cubeとして適用した場合

おまけ: Texture2DとCubemapの差異を補正しない場合

  • 以下のように各テクスチャの向きがおかしくなります
  • Cubemapとして適用してもシームレスではなくなっています

f:id:tsgcpp:20200701201755p:plain

f:id:tsgcpp:20200701202104j:plain
TextureShape: Cubeとして適用した場合

生成した画像をCubemapとして適用

  • 作成した画像は2次元テクスチャなので、Cubemapとして適用してください
    • TextureShape: Cube
    • Mapping: 6 Frames Layout (Cubic Environment)

※現時点では特にEditorGUILayout.PropertyFieldなどを使った自動設定は作成していません

f:id:tsgcpp:20200701203322j:plain

Github

2021/06/19追記

諸々更新してツールの見た目が変わっています。
使用方法はREADMEに記載されているYoutubeの動画を参考にしてください

github.com

※プロジェクトサイズ削減のためサンプルシーンは別物になっています

雑感

ちょっとこういったツールがほしくなったので作ってみました。
もしかしたら何らかの形で配布されているのかもしれませんが見つかりませんでした。。。
もしご存知の方がいましたら教えていただけるとありがたいです!

ちょっとCubemap.GetPixelsの差異の部分で詰まりましたが、ひとまずほしかったものは作れました。

良かったら使ってみて下さい!
感想や問題報告などもいただけるとありがたいです。

それでは~。