Version: 2021.3
言語: 日本語
デスクトップ向けのプラグインのビルド
低レベルのネイティブプラグインレンダリング拡張

低レベルのネイティブプラグインインターフェース

Unity の ネイティブプラグイン は、特定のイベントが発生したときにコールバックを受け取ることができます。これを利用して、プラグインに低レベルレンダリングを実装し、Unity のマルチスレッドレンダリングと連携できます。

インターフェースレジストリ

Unity のメインイベントを処理するために、プラグインは UnityPluginLoadUnityPluginUnload 関数をエクスポートする必要があります。IUnityInterfaces はプラグインがこれらの関数にアクセスすることを可能にします。IUnityInterfaces はプラグイン API の IUnityInterface.h にあります。

# include "IUnityInterface.h"
# include "IUnityGraphics.h"
// Unity プラグイン load イベント
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
    UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
    IUnityGraphics* graphics = unityInterfaces->Get<IUnityGraphics>();
}

グラフィックスデバイスへのアクセス

IUnityGraphics.h にある IUnityGraphics インターフェースを使用すると、プラグインが汎用グラフィックスデバ イス機能にアクセスできるようになります。このスクリプトは、IUnityGraphics インターフェースを使用して、コールバックを登録する方法を示します。

# include "IUnityInterface.h"
# include "IUnityGraphics.h"
    
static IUnityInterfaces* s_UnityInterfaces = NULL;
static IUnityGraphics* s_Graphics = NULL;
static UnityGfxRenderer s_RendererType = kUnityGfxRendererNull;
    
// Unityプラグインロードイベント
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
    UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
    s_UnityInterfaces = unityInterfaces;
    s_Graphics = unityInterfaces->Get<IUnityGraphics>();
        
    s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent);
        
    // グラフィックデバイスがすでに初期化されている場合にイベントを見逃さないようにするため
   // プラグインのロード時に手動で OnGraphicsDeviceEvent(initialize) を実行する。
    OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize);
}
    
// ユニティプラグインのアンロードイベント
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
    UnityPluginUnload()
{
    s_Graphics-&gt;UnregisterDeviceEventCallback(OnGraphicsDeviceEvent);

    
static void UNITY_INTERFACE_API
    OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType)

    switch (eventType)
    {
        case kUnityGfxDeviceEventInitialize:
        {
            s_RendererType = s_Graphics->GetRenderer();
            //ユーザー初期化コード記入
            break;
        }
        case kUnityGfxDeviceEventShutdown:
        {
            s_RendererType = kUnityGfxRendererNull;
            //ユーザーシャットダウンコード記入
            break;
        }
        case kUnityGfxDeviceEventBeforeReset:
        {
            //ユーザーの Direct3D 9 コード記入
            break;
        }
        case kUnityGfxDeviceEventAfterReset:
        {
            //:ユーザーの Direct3D 9 コード記入
            break;
        }
    };
}

レンダースレッドのプラグインコールバック

プラットフォームと使用可能な CPU の数が許す限り、Unity でマルチスレッドを使用してレンダリングすることができます。

ノート: マルチスレッドレンダリングを使用すると、レンダリング API のコマンドは、MonoBehaviour スクリプトを実行するスレッドとは完全に別のスレッドで実行されます。メインスレッドとレンダースレッドの間で通信が行われるため、メインスレッドがレンダースレッドに渡した作業量によっては、プラグインがすぐにレンダリングを開始しない場合があります。

プラグインからレンダリングするには、マネージプラグインスクリプトから GL.IssuePluginEvent を呼び出します。これにより、下のコード例に示すように、Unity のレンダーパイプラインは、レンダースレッドからネイティブ関数を呼び出します。例えば、Camera の OnPostRender 関数から GL.IssuePluginEvent を呼び出すと、この関数は、カメラがレンダリングを終了するとすぐにプラグインコールバックを呼び出します。

ネイティブプラグインのコード

// 特定のレンダリングイベントを処理するプラグイン関数
static void UNITY_INTERFACE_API OnRenderEvent(int eventID)
{
    //ユーザーのレンダリングコード
}
    
// プラグイン特有のスクリプトにコールバックを渡すための自由に定義した関数
extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
    GetRenderEventFunc()
{
    return OnRenderEvent;
}

マネージプラグインコード

# if UNITY_IPHONE && !UNITY_EDITOR
[DllImport ("__Internal")]
# else
[DllImport("RenderingPlugin")]
# endif
private static extern IntPtr GetRenderEventFunc();

// 指定のコールバックがレンダースレッドで呼び出されるようにキューで待機
GL.IssuePluginEvent(GetRenderEventFunc(), 1);

UnityRenderingEvent コールバックのシグネチャは、Native Rendering Plugin サンプルの IUnityGraphics.h で提供されています。

OpenGL グラフィックス API を使用したプラグイン

OpenGL オブジェクトには 2 種類あります。

  • OpenGL コンテキスト間で共有されるオブジェクト テクスチャ、バッファ、レンダーバッファ、サンプラー、クエリ、シェーダー、 プログラムオブジェクトなど。
  • OpenGLごとのコンテキストオブジェクト 頂点配列、フレームバッファ、プログラムパイプライン、変換フィードバック、同期オブジェクトなど。

Unity は複数の OpenGL コンテキストを使用します。エディターとプレイヤーの起動と終了時にはマスターコンテキストに依存し、レンダリング時には専用のコンテキストを使用します。つまり、 kUnityGfxDeviceEventInitializekUnityGfxDeviceEventShutdown イベント中にコンテキストごとのオブジェクトを作成することはできません。


• 2017–05–16 修正されたページ

デスクトップ向けのプラグインのビルド
低レベルのネイティブプラグインレンダリング拡張