Panorama180 Render : Tips : OBS Studioにパノラマ画像を送る

Developer : ft-lab (Yutaka Yoshisaka).
03/04/2022 - 03/04/2022.

戻る

概要

OBS Studio ( https://obsproject.com/ )にPanorama180 Renderのパノラマレンダリングを送ります。
Unity 2021.2.1 + URPで動作確認しました。
また、OBS Studioと連携する際に「UnityCapture」( https://github.com/schellingb/UnityCapture )を使用しました。

インストール

大きく、以下の項目に分かれます。

OBS Studioのインストール

OBS Studioをあらかじめインストールしておきます。
https://obsproject.com/

UnityCaptureのインストール

UnityCapture ( https://github.com/schellingb/UnityCapture)をダウンロードします。

zipファイルを解凍します。
注意点として、解凍した際のフォルダ一式はUnityCaptureのインストール処理後も削除しないようにしてください。
「UnityCapture-master/Install/Install.bat」をエクスプローラでダブルクリックして実行します。

この操作により、OBSに「Unity Video Capture」デバイスが追加されます。

OBSで「Unity Video Capture」を指定/準備

OBSを起動し、Sourcesで「+」ボタンを押し「Video Capture Device」を選択します。

「Create/Select Source」ウィンドウで「Unity Capture Device」という名前に変更しました。この名前は何でもいいです。

Propertiesウィンドウが表示されるため、「Device」で「Unity Video Device」を選択します。

「Resolution/FPS Type」は「Custom」を選択し、「Resolution」で「1920x1080」を選択します。
この時の解像度は、Unity側で出力するRenderTextureサイズと同じである必要があります。
OKボタンを押して閉じます。

これでOBS側の準備が整いました。
以下の状態で待機しておきます。

UnityでRenderTextureをOBSに渡す

Unity EditorでPanorama180 RenderのレンダリングをOBSに渡すための準備を行います。

必要なファイルをプロジェクトに追加

「Panorama180 Render」アセットをプロジェクトに追加します。

「UnityCapture」より、"UnityCapture-master/UnityCaptureSample/Assets"をプロジェクトに追加し、 フォルダ名を"UnityCapture"にリネームしました。

ここには、OBSにアクセスするためのdllも含まれています。

CameraにComponentを追加

ここではURPのサンプルシーンを使用しています。

MainCameraを選択し、Inspectorウィンドウで"Panorama180 Render"を追加します。
Inspectorの一番下の「Add Component」ボタンを押して対象のコンポーネント名を検索することができます。


この状態で実行すると、Panorama180 Renderのパノラマ180-3Dの表示が行われます。
まだOBSとは連携していません。

スクリプトを記載

Panorama180 Renderからのレンダリングを行う処理をスクリプトで記載し、 そのレンダリングをRenderTextureとしてOBSに渡します。
これは、Panorama180 Renderのサンプル"Demo/Scripts/Runtime/Sample_Capture.cs"を参考にしました。

[SampleCaptureToOBS.cs]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Panorama180RenderSample {
    using Panorama180Render = Panorama180Render.Panorama180Render;
    using UnityCapture = UnityCapture;

    public class SampleCaptureToOBS : MonoBehaviour {
        private Panorama180Render m_panorama180Render = null;
        private UnityCapture.Interface m_captureInterface = null;

        void Start () {
            // Get Panorama180Render component from MainCamera.
            if (Camera.main != null) {
                GameObject g = Camera.main.gameObject;
                if (g != null) {
                    m_panorama180Render = g.GetComponent();
                }
            }
            if (m_panorama180Render == null) {
                Debug.Log("The Panorama180Render component is not assigned to MainCamera.");
                return;
            }

            //------------------------------------------------.
            // Set the parameters of Panorama180 Render.
            //------------------------------------------------.
            // Set GameViewMode (Default view).
            m_panorama180Render.SetGameViewMode(Panorama180Render.GameViewMode.Default);

            // Set IPD(Interpupillary distance. unit m).
            m_panorama180Render.SetIPD(0.064f);

            // Set texture size as Cubemap (512/1024/2048/4096/8192).
            m_panorama180Render.SetRenderTextureSize(1024);

            // Post Processing On / Off.
            m_panorama180Render.SetPostProcessing(true);

            // Set Panorama180.
            m_panorama180Render.SetPanoramaMode(Panorama180Render.PanoramaMode.Panorama180);

            // Set Stereo.
            m_panorama180Render.SetEyesType(Panorama180Render.EyesType.Stereo);

            // Output resolution at Panorama180.
            m_panorama180Render.SetOutputTextureSizeType(Panorama180Render.OutputTextureSizeType._1024);

            // Begin capture.
            m_panorama180Render.BeginCapture();

            //------------------------------------------------.
            // Create UnityCapture.
            //------------------------------------------------.
            m_captureInterface = new UnityCapture.Interface(UnityCapture.ECaptureDevice.CaptureDevice1);
        }

        void OnDestroy () {
            if (m_captureInterface != null) m_captureInterface.Close();
            if (m_panorama180Render != null) m_panorama180Render.EndCapture();
        }

        void Update () {
            if (m_captureInterface != null) {
                // Get RenderTexture.
                RenderTexture rt = m_panorama180Render.GetRenderTexture();

                // Resize to fit OBS texture size.
                int rWidth  = 1920;
                int rHeight = 1080;
                RenderTexture tmpRT = RenderTexture.GetTemporary(rWidth, rHeight, 0, RenderTextureFormat.ARGB32);
                Graphics.Blit(rt, tmpRT);

                // Send RenderTexture to OBS.
                UnityCapture.ECaptureSendResult result = m_captureInterface.SendTexture(tmpRT);

                RenderTexture.ReleaseTemporary(tmpRT);
            }
        }
    }
}
ダウンロード : SampleCaptureToOBS.cs

それぞれのコードを説明していきます。
カレントのスコープ内でそれぞれのClassにアクセスできるようにします。
using Panorama180Render = Panorama180Render.Panorama180Render;
using UnityCapture = UnityCapture;

開始時の処理 : MainCameraを取得し、その中のコンポーネント「Panorama180Render」を取得します。
if (Camera.main != null) {
    GameObject g = Camera.main.gameObject;
    if (g != null) {
        m_panorama180Render = g.GetComponent();
    }
}

開始時の処理 : Panorama180 Renderのパラメータを割り当てます。
// Set GameViewMode (Default view).
m_panorama180Render.SetGameViewMode(Panorama180Render.GameViewMode.Default);

// Set IPD(Interpupillary distance. unit m).
m_panorama180Render.SetIPD(0.064f);

// Set texture size as Cubemap (512/1024/2048/4096/8192).
m_panorama180Render.SetRenderTextureSize(1024);

// Post Processing On / Off.
m_panorama180Render.SetPostProcessing(true);

// Set Panorama180.
m_panorama180Render.SetPanoramaMode(Panorama180Render.PanoramaMode.Panorama180);

// Set Stereo.
m_panorama180Render.SetEyesType(Panorama180Render.EyesType.Stereo);

// Output resolution at Panorama180.
m_panorama180Render.SetOutputTextureSizeType(Panorama180Render.OutputTextureSizeType._1024);
パノラマ180-3Dの2048 x 1024ピクセルの画像を作成する指定になります。

開始時の処理 : Panorama180 Renderのキャプチャ処理を開始します。
// Begin capture.
m_panorama180Render.BeginCapture();

開始時の処理 : UnityCaptureのインターフェースの作成を行います。
m_captureInterface = new UnityCapture.Interface(UnityCapture.ECaptureDevice.CaptureDevice1);

更新時の処理 : Panorama180 Renderのレンダリング結果のRenderTextureを取得します。
RenderTexture rt = m_panorama180Render.GetRenderTexture();

更新時の処理 : RenderTextureをリサイズします。
int rWidth  = 1920;
int rHeight = 1080;
RenderTexture tmpRT = RenderTexture.GetTemporary(rWidth, rHeight, 0, RenderTextureFormat.ARGB32);
Graphics.Blit(rt, tmpRT);
このときのリサイズ後のRenderTextureのサイズは、OBSで指定したResolutionの指定と同じである必要があります。
この処理でtmpRTにリサイズ後のRenderTextureが格納されます。

更新時の処理 : UnityCaptureにRenderTextureを送ります。
UnityCapture.ECaptureSendResult result = m_captureInterface.SendTexture(tmpRT);
戻り値のエラーコードは、UnityCaptureのサンプルやドキュメントをご参照くださいませ。

更新時の処理 : 作業用のRenderTextureを破棄します。
RenderTexture.ReleaseTemporary(tmpRT);

終了時の破棄処理です。
if (m_captureInterface != null) m_captureInterface.Close();
if (m_panorama180Render != null) m_panorama180Render.EndCapture();

空のGameObjectを作成し、スクリプトを割り当て

空のGameObjectを作成します。
これに、前述した「SampleCaptureToOBS.cs」をコンポーネントとして追加します。


以上で実装が完了しました。

実行

Playボタンを押して実行します。
実行を行うとUnity Editor側はカメラからの通常のレンダリングが行われます。
OBS側ではパノラマ180-3Dのレンダリング結果が表示されます。


Unity Editorの左上のメッセージを消す場合は、
MainCameraに割り当てたPanorama180 Renderコンポーネントのパラメータの「Show Info」チェックボックスをOffにしてください。

戻る