#ChannelPlayer · Unity · VRソフト

静止画のGamma → Linear 変換

Channel Playerでは、動画だけでなく静止画の描画も実装している。静止画だが180/LRフォーマットで、3D表示させる実装は今まで実現していなかったので現在実装中である。ちなみに参考にしているサイトはUnity_Panorama180Viewである。

静止画を一度表示した後で、2D/Monoから、180/LRにフォーマットを変換した場合、動画とは異なりTextureに再ロードが必要となるが、SteamVR版に比べQuest版は異様に遅いので、どこに問題があるか調べていた。

結論は、Texture2Dに展開後のGamma→Linear変換に時間がかかっていた。8000×4000ドットの静止画だと、大体4秒ぐらいかかる。

Quest版は、SteamVR版のUnity環境のビルドターゲットをWindowsからAndroidに変えたものであるので、基本的には全く同じように動作するはずである。しかし、SciFiシアターシーンでは問題無いが、Playerシーンでは、どうしても暗い映像となってしまい、Ver1.28以前では、ビルド時の色空間をLinearではなくGammaとしていた。

Ver1.29では色空間をLinearにした結果、SciFiシアターシーンも明るくなったが、Playerシーンでは、静止画表示の際、Gamma→Linearに変換することが必要となった。

それでも1920×1080程度の大きさの静止画であれば問題無かったが、評価用に用いた静止画の180/LRの静止画はその約16倍の面積であり、このときのGamma→Linear変換の時間が長くなってた。

Gamma→Linear変換は、RenderTexture(Texture2D)を画像保存すると暗い時での取り組みを参考にして、以下のようなコードを書いていた。

    private void gamma_correct(Texture2D tex)
    {
#if UNITY_ANDROID
        if (tex != null)
        {
            // ガンマ補正
            var color = tex.GetPixels();
            //Debug.Log(DateTime.Now.ToString("HH:mm:ss.fff") + ": 13 LinearToGammaSpace start");
            for (int i = 0; i < color.Length; i++)
            {
                color[i].r = Mathf.LinearToGammaSpace(color[i].r);
                color[i].g = Mathf.LinearToGammaSpace(color[i].g);
                color[i].b = Mathf.LinearToGammaSpace(color[i].b);
            }
            //Debug.Log(DateTime.Now.ToString("HH:mm:ss.fff") + ": 14 LinearToGammaSpace done");
            tex.SetPixels(color);
            //Debug.Log(DateTime.Now.ToString("HH:mm:ss.fff") + ": 15 tex.SetPixels(color) done");            
        }
#endif
    }

でも、ここに時間がかかることが判ったので、【Unity】【C#】ガンマ(Gamma, sRGB) – リニア(Linear) 値の相互変換  の情報を参考にして、以下コードに書き換えた。その結果、約4秒が0.8秒ぐらに短縮できた。その他の処理もあるので、8000×4000ドットの静止画だと残念ながらページめくるだけでも2秒ほどかかる。Quest 2はそもそも片目2Kぐらいの解像度なんだから、もっと小さい面積の静止画で十分だろうとは思う。

    private void gamma_correct(Texture2D tex)
    {
#if UNITY_ANDROID
        if (tex != null)
        {
            // ガンマ補正
            var color = tex.GetPixels();
            //Debug.Log(DateTime.Now.ToString("HH:mm:ss.fff") + ": 13 LinearToGammaSpace start");
            for (int i = 0; i < color.Length; i++)
            {
                //color[i].r = Mathf.LinearToGammaSpace(color[i].r);
                //color[i].g = Mathf.LinearToGammaSpace(color[i].g);
                //color[i].b = Mathf.LinearToGammaSpace(color[i].b);
                color[i].r = linearValue(color[i].r);
                color[i].g = linearValue(color[i].g);
                color[i].b = linearValue(color[i].b);
            }
            //Debug.Log(DateTime.Now.ToString("HH:mm:ss.fff") + ": 14 LinearToGammaSpace done");
            tex.SetPixels(color);
            //Debug.Log(DateTime.Now.ToString("HH:mm:ss.fff") + ": 15 tex.SetPixels(color) done");            
        }
#endif
    }

    private float linearValue(float gamma)
    {
        return gamma * (gamma * (gamma * 0.305306011f + 0.682171111f) + 0.012522878f);
    }
広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中