【Unity】【エディタ拡張】キューブマップを簡単に作るエディタ拡張

f:id:halya_11:20180712230835p:plain

キューブマップを簡単に作るためのエディタ拡張です。

Unity2017.4.1

やりたいことと方針

今のシーンの中央からレンダリングしたキューブマップを作ります。

f:id:halya_11:20180712225241p:plain

調べるとCamera.RenderToCubemap()というメソッドを使った実装例が出てきますが、
旧キューブマップのように6枚のテクスチャを保存してたりしてイマイチです。

かといって自分で1枚のテクスチャにまとめるのも面倒なので、Reflection Probeを利用してみました。
Reflection Probeはキューブマップを作るための機能なのだから道理は通っているはずです。

実装

#if UNITY_EDITOR
using UnityEngine;
using UnityEditor;

public class CubemapCreator
{

    [MenuItem("Assets/Create Cubemap 128x128")]
    public static void CreateCubemap128()
    {
        CreateCubemap(128);
    }

    [MenuItem("Assets/Create Cubemap 256x256")]
    public static void CreateCubemap256()
    {
        CreateCubemap(256);
    }

    [MenuItem("Assets/Create Cubemap 512x512")]
    public static void CreateCubemap512()
    {
        CreateCubemap(512);
    }
    
    private static void CreateCubemap(int px)
    {
        // Reflection Probeを配置
        var probeGO = new GameObject("Cubemap Capture Probe");
        var probe = probeGO.AddComponent<ReflectionProbe>();
        var probeSO = new SerializedObject(probe);
        probeGO.transform.position = Vector3.zero;
        probeGO.transform.rotation = Quaternion.identity;

        // 設定したい項目があればここで設定
        probe.mode = UnityEngine.Rendering.ReflectionProbeMode.Custom;
        probe.resolution = px;
        probe.hdr = false;
        probe.boxProjection = false;
        probeSO.Update();
        probeSO.FindProperty("m_RenderDynamicObjects").boolValue = true;
        probeSO.ApplyModifiedProperties();

        // デフォルトパスを生成
        string ext = probe.hdr ? "exr" : "png";
        var path = UnityEditor.SceneManagement.EditorSceneManager.GetActiveScene().path;
        if (!string.IsNullOrEmpty(path)) {
            path = System.IO.Path.GetDirectoryName(path);
        }
        if (string.IsNullOrEmpty(path)) {
            path = "Assets";
        }

        // ディレクトリがなければ作る
        else if (System.IO.Directory.Exists(path) == false) {
            System.IO.Directory.CreateDirectory(path);
        }

        // ファイル保存パネルを表示
        var fileName = "name." + ext;
        fileName = System.IO.Path.GetFileNameWithoutExtension(AssetDatabase.GenerateUniqueAssetPath(System.IO.Path.Combine(path, fileName)));
        path = EditorUtility.SaveFilePanelInProject("Save Cubemap", fileName, ext, "", path);

        if (!string.IsNullOrEmpty(path)) {
            // ベイク
            EditorUtility.DisplayProgressBar("Cubemap", "Baking...", 0.5f);
            if (!Lightmapping.BakeReflectionProbe(probe, path)) {
                Debug.LogError("Failed to bake cubemap");
            }
            EditorUtility.ClearProgressBar();
        }

        GameObject.DestroyImmediate(probeGO);
    }
}
#endif

やっていることは

  1. Reflection Probeをシーンの中央に生成する
  2. ベイクする

これだけです。

HDRは切っていますが有効にしても問題ないです。
また、今回はテクスチャが欲しいだけなのでボックスプロジェクションはOFF。

そしてmodeをCustomにしてm_RenderDynamicObjectsをtrueにすることで動的なオブジェクトも映しています。
ここは変数公開されていないのでSerializedObjectで。
不要であればfalseにしてください。

結果

Projectビューで右クリック > Create Cubemap で生成できます。

f:id:halya_11:20180712231351p:plain

このようなキューブマップが生成されました。

f:id:halya_11:20180712230835p:plain

pngは横長のものになりました。

f:id:halya_11:20180712231150p:plain

なお、このスクリプトはUnity2017.4.1で動作確認しています。
Unity2018からこの辺り変わっていきそうな予感がするので、もし動かなかったらご一報いただけますと幸いですm(_ _ )m

関連

light11.hatenadiary.com