夜風のMixedReality

xRと出会って変わった人生と出会った技術を書き残すためのGeekなHoloRangerの居場所

UnityRenderStreamingでスマホARを実装する 背景の透過 その①

本日はUnity枠です。

先日よりRenderStreamingを触っていますが、スマートフォンARまで実装しました。

ARといってもARFoundationの機能を使用してカメラを動かしている実装で、どちらかというと現実情報をベースとしたARではなくVR的な実装になっています。

今回はSkyBoxにスマートフォンのカメラ映像を用いてARを実装できないかチャレンジします。

〇RenderSreamingでの送信データ

RenderStreamingではCameraScreenTextureの3タイプがサンプルで送信形式として提供されています。(+WebCamもあるようです。)

それぞれScreenがEditor上のGameViewをそのままストリーミング、CameraがEditor上のGameViewに映像を送らずにカメラの情報をそのまま送信、Textureがソースとして選択可能です。

これはVideo StreamSender.csVideoSourceTypeを変更しています。

送信側のUnityプロジェクトのカメラレンダリングデータを映像としてストリーミングしています。

一般的に送信されるデータは通信データの最適化の関係でRGBの形式がとられており、透明度であるアルファが入っておらず受信先で透明度の情報を用いるためには送信形式を見直す必要があります。

サンプルではMainCameraにアタッチされています。

送信データはVideoSourceTypeによってswitch文で分けられています。

VideoStreamSourceImpl CreateVideoStreamSource()
        {
            switch (m_Source)
            {
                case VideoStreamSource.Camera:
                    return new VideoStreamSourceCamera(this);
                case VideoStreamSource.Screen:
                    return new VideoStreamSourceScreen(this);
                case VideoStreamSource.Texture:
                    return new VideoStreamSourceTexture(this);
                case VideoStreamSource.WebCamera:
                    return new VideoStreamSourceWebCam(this);
            }
            throw new InvalidOperationException("");
        }

例えばTextureのタイプで実際にカメラ映像をRGBのデータにしているのはVideoStreamSourceTextureクラスです。

        class VideoStreamSourceTexture : VideoStreamSourceImpl
        {
            Texture m_texture;
            Texture m_copyTexture;
            private Coroutine m_coroutineScreenCapture;
            private MonoBehaviour m_behaviour;

            public VideoStreamSourceTexture(VideoStreamSender parent) : base(parent)
            {
                Texture texture = parent.m_Texture;
                if (texture == null)
                    throw new ArgumentNullException("texture", "The sourceTexture is not assigned.");
                m_texture = texture;
                m_behaviour = parent;
            }

            public override WaitForCreateTrack CreateTrack()
            {
                var instruction = new WaitForCreateTrack();

                GraphicsFormat format =
                    WebRTC.WebRTC.GetSupportedGraphicsFormat(SystemInfo.graphicsDeviceType);
                if (m_texture.graphicsFormat == format && m_texture.width == width && m_texture.height == height)
                {
                    instruction.Done(new VideoStreamTrack(m_texture));
                    return instruction;
                }

                m_copyTexture = new Texture2D(width, height, format, TextureCreationFlags.None);
                m_coroutineScreenCapture = m_behaviour.StartCoroutine(RecordScreenFrame());
                instruction.Done(new VideoStreamTrack(m_copyTexture));
                return instruction;
            }

            public override void Dispose()
            {
                if (m_copyTexture != null)
                {
                    Destroy(m_copyTexture);
                    m_copyTexture = null;
                }

                if (m_coroutineScreenCapture != null)
                {
                    m_behaviour.StopCoroutine(m_coroutineScreenCapture);
                    m_behaviour = null;
                    m_coroutineScreenCapture = null;
                }
                GC.SuppressFinalize(this);
            }

            ~VideoStreamSourceTexture()
            {
                Dispose();
            }

            IEnumerator RecordScreenFrame()
            {
                while (true)
                {
                    yield return new WaitForEndOfFrame();

                    Graphics.ConvertTexture(m_texture, m_copyTexture);
                }
            }
        }

この中でm_copyTextureが送信するデータとしてのテクスチャを作成しているメソッドになります。

                m_copyTexture = new Texture2D(width, height, format, TextureCreationFlags.None);

新規のテクスチャを作成するにあたり第三引数のformatをRGBAに対応した形式に直します。

  m_copyTexture = new Texture2D(width, height, GraphicsFormat.R8G8B8A8_SRGB, TextureCreationFlags.None);

ただしRenderStreamingのスクリプトはPackageManagerで管理されており、編集が効きません。

次回編集できるようにしていきます。

本日は以上です。