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

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

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 plugin load event
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
    UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
    s_UnityInterfaces = unityInterfaces;
    s_Graphics = unityInterfaces->Get<IUnityGraphics>();
        
    s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent);
        
    // Run OnGraphicsDeviceEvent(initialize) manually on plugin load
    // to not miss the event in case the graphics device is already initialized
    OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize);
}
    
// Unity plugin unload event
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
    UnityPluginUnload()
{
    s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent);
}
    
static void UNITY_INTERFACE_API
    OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType)
{
    switch (eventType)
    {
        case kUnityGfxDeviceEventInitialize:
        {
            s_RendererType = s_Graphics->GetRenderer();
            //TODO: user initialization code on graphics device initialization. 
            For example, D3D11 resource creation.
            break;
        }
        case kUnityGfxDeviceEventShutdown:
        {
            s_RendererType = kUnityGfxRendererNull;
            //TODO: user graphics API code to call on graphics device shutdown.
            break;
        }
        case kUnityGfxDeviceEventBeforeReset:
        {
            //TODO: user graphics API code to call before graphics device reset.
            break;
        }
        case kUnityGfxDeviceEventAfterReset:
        {
            //TODO: user graphics API code to call after graphics device reset.
            break;
        }
    };
}

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

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

Note: When you use multithreaded rendering, the rendering API commands happen on a thread that’s completely separate from the thread that runs MonoBehaviour scripts. The communication between the main thread and the render thread means that your plug-in might not start rendering immediately, depending on how much work the main thread has pushed to the render thread.

プラグインからレンダリングするには、マネージプラグインスクリプトから 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 uses multiple OpenGL contexts. When initializing and closing the Editor and the Player, Unity relies on a master context, but when rendering it uses dedicated contexts. That is, you can’t create per-context objects during kUnityGfxDeviceEventInitialize and kUnityGfxDeviceEventShutdown events.


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