用于本机插件开发的Unity图形仿真器(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/unity-graphics-emulator-for-native-plugin-developm-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 15 分钟阅读 - 7089 个词 阅读量 0用于本机插件开发的Unity图形仿真器(译文)
原文地址:https://www.codeproject.com/Articles/1216876/Unity-Graphics-Emulator-for-Native-Plugin-Developm
原文作者:EgorYusov
译文由本站 robot-v1.0 翻译
前言
This article describes Unity low-level plugin interface and the Unity graphics interface emulator that facilitates native plugin development.
本文介绍了Unity低级插件界面和促进本机插件开发的Unity图形界面仿真器.
介绍(Introduction)
统一(Unity) 是一个非常受欢迎的游戏引擎,具有令人印象深刻的工具箱.但是,很难提供潜在客户可能需要的所有功能,因此Unity以以下形式支持扩展机制:(is a very popular game engine with quite impressive toolbox. However, it is very hard to provide every feature a potential customer may need, so Unity supports extension mechanism in the form of) 本机插件(native plugins) 由包含本机代码的动态库实现.这些插件可能包含通用功能,以及Direct3D11,Direct3D12或OpenGL/GLES等低级API中的图形命令.本机渲染插件通过以下方式与Unity通信(implemented by dynamic libraries containing native code. These plugins may contain general-purpose functionality, as well as graphics commands in low-level API such as Direct3D11, Direct3D12, or OpenGL/GLES. Native rendering plugins communicate with Unity through) IUnityGraphics
接口.(interface.)
由于多种原因,本机插件开发可能并不总是那么简单.首先,Unity不支持热插件重新加载.动态库一旦加载,就永远不会卸载.可能可以针对此问题创建解决方法(例如编写仅加载真正的动态库的代理插件),但这会带来额外的复杂性,并且可能不适用于所有平台.其次,在开发插件时,使Unity编辑器崩溃非常容易.重新启动编辑器并重新加载场景会增加迭代时间.最后,附加到正在运行的编辑器以调试插件当然是可能的,但可能并不总是最佳的.(Native plugin development may not always be straightforward due to a number of reasons. First, Unity does not support hot plugin reload. Once dynamic library is loaded, it is never offloaded. It may be possible to create a workaround for this issue (such as writing a proxy plugin that only loads real dynamic library), but this introduces additional complexity and may not work on all platforms. Second, when plugin is under development, it is very easy to crash Unity editor. Restarting the editor and reloading the scene increases iteration times. Finally, attaching to running editor to debug the plugin is certainly possible, but may not always be optimal.)
由于上述原因,拥有模拟Unity接口的隔离环境以促进本机插件开发会更加方便.本文介绍了这种环境.它模拟Unity图形界面,目前在Windows桌面平台上支持Direct3D11,Direct3D12和OpenGL,在通用Windows平台上支持Direct3D11和Direct3D12,在Android上支持OpenGLES.(Due to the reasons above, it would be much more convenient to have isolated environment that emulates Unity interfaces to facilitate native plugin development. This article describes such environemnt. It emulates Unity graphics interfaces and currently supports Direct3D11, Direct3D12, and OpenGL on Windows Desktop platform, Direct3D11 and Direct3D12 on Universal Windows Platform, and OpenGLES on Android.) 完整的源代码(The full source code) 免费使用,可在GitHub上使用.(is free for use and available on GitHub.)
背景(Background)
对底层图形API的一些理解,例如(Some understanding of low-level grpahics APIs such as) Direct3D11(Direct3D11) ,(,) Direct3D12(Direct3D12) , 要么(, or) 的OpenGL(OpenGL) /(/) 格莱斯(GLES) 以及(as well as) Unity本机插件界面(Unity native plugin interfcae) 是可取的.(is desirable.)
Unity图形界面(Unity Graphics Interfaces)
本部分描述了Unity图形界面,该界面允许本机插件访问低级图形API并发出绘制命令.有关详细信息,请参见(This section describes Unity graphics interfaces that allow native plugins access low-level graphics API and issue draw commands. Detailed information can be found on) Unity帮助页面(Unity help pages) .(.) 要被识别为图形插件,该库应导出以下两个功能:(To be recognized as a graphics plugin, the library should export the following two functions:)
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
UnityPluginLoad(IUnityInterfaces* unityInterfaces);
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
UnityPluginUnload();
UnityPluginLoad()
插件动态库加载后,Unity会自动调用它.(is automatically called by Unity when a plugin dynamic library is loaded.) UnityPluginUnload()
显然应该在卸载插件时调用该函数,但是在我的实验中,我从未见过该函数(Unity 2017.1.1f1,Windows 64位).(is apparently supposed to be called when the plugin is unloaded, but in my experiments I’ve never seen the function called (Unity 2017.1.1f1, Windows 64-bit).)
UnityPluginLoad()
得到一个指向(gets a pointer to) IUnityInterfaces
,这是插件与Unity交互的主要界面.此函数的典型实现是存储指针,请求指向(, which is the main interface for the plugin to interact with Unity. A typical implementation of this function stores the pointer, requests a pointer to) IUnityGraphics
接口,寄存器(interface, registers) OnGraphicsDeviceEvent()
回调并手动调用它:(callback and manually calls it:)
static IUnityInterfaces* s_UnityInterfaces = nullptr;
static IUnityGraphics* s_Graphics = nullptr;
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API
UnityPluginLoad(IUnityInterfaces* unityInterfaces)
{
s_UnityInterfaces = unityInterfaces;
s_Graphics = s_UnityInterfaces->Get<IUnityGraphics>();
s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent);
// Run OnGraphicsDeviceEvent(initialize) manually on plugin load
OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize);
}
IUnityGraphics
接口不提供对低级API的访问.其第一个目标是注册图形设备事件回调(interface does not provide access to the low-level API. Its first goal is to register the graphics device event callback) OnGraphicsDeviceEvent()
.发生以下事件之一时,将调用回调:(. The callback is called when one of the following events happen:)
- 图形设备初始化((Graphics device initialization ()
kUnityGfxDeviceEventInitialize
)()) - 图形设备关闭((Graphics device shutdown ()
kUnityGfxDeviceEventShutdown
)()) - 图形设备即将被重置(Graphics device is about to be reset ()
kUnityGfxDeviceEventBeforeReset
).此事件仅在Direct3D9 API中发生,因此与我们无关.(). This event only happens with Direct3D9 API, and is thus irrelevant for us.) - 图形设备刚刚被重置((Graphics device has just neen reset ()
kUnityGfxDeviceEventAfterReset
).类似,此事件特定于Direct3D9,并且是无关的.(). Similar, this event Direct3D9-specific and is irrelevant.) 第二个目标(The second goal of)IUnityGraphics
界面是通过以下方式报告Unity使用的低级API(interface is to report the low level API used by Unity through)GetRenderer()
功能.该函数可能返回各种值,但我们仅支持以下渲染器:(function. The function may return a variety of values, but we only support the following renderers:)kUnityGfxRendererD3D11
,(,)kUnityGfxRendererD3D12
,(,)kUnityGfxRendererOpenGLCore
和(, and)kUnityGfxRendererOpenGLES30
.(.)OnGraphicsDeviceEvent()
因此需要处理(thus needs to handle)kUnityGfxDeviceEventInitialize
和(and)kUnityGfxDeviceEventShutdown
事件:(events:)
static UnityGfxRenderer s_DeviceType = kUnityGfxRendererNull;
void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType)
{
// Create graphics API implementation upon initialization
if (eventType == kUnityGfxDeviceEventInitialize)
{
// Get render API
s_DeviceType = s_Graphics->GetRenderer();
CreateRenderAPI(s_DeviceType);
if (s_CurrentAPI)
s_CurrentAPI->ProcessDeviceEvent(eventType, s_UnityInterfaces);
}
else if (eventType == kUnityGfxDeviceEventShutdown)
{
// Cleanup graphics API implementation upon shutdown
// We must destroy all resources before releasing the API
g_SamplePlugin.reset();
if (s_CurrentAPI)
{
s_CurrentAPI->ProcessDeviceEvent(eventType, s_UnityInterfaces);
s_CurrentAPI.reset();
}
s_DeviceType = kUnityGfxRendererNull;
}
else if (s_CurrentAPI)
{
// Let the implementation process the device related events
s_CurrentAPI->ProcessDeviceEvent(eventType, s_UnityInterfaces);
}
}
CreateRenderAPI()
是用于初始化插件以使用特定的低级API的函数.我们支持Direct3D11,Direct3D12和OpenGL/GLES,因此函数如下所示:(is the function that initializes the plugin to work with the specific low-level API. We support Direct3D11, Direct3D12, and OpenGL/GLES, so the function looks like this:)
static std::unique_ptr<RenderAPI> s_CurrentAPI;
void CreateRenderAPI(UnityGfxRenderer apiType)
{
#if SUPPORT_D3D11
if (apiType == kUnityGfxRendererD3D11)
{
s_CurrentAPI.reset( CreateRenderAPI_D3D11() );
}
#endif // if SUPPORT_D3D11
#if SUPPORT_D3D12
if (apiType == kUnityGfxRendererD3D12)
{
s_CurrentAPI.reset( CreateRenderAPI_D3D12() );
}
#endif // if SUPPORT_D3D9
#if SUPPORT_OPENGL_UNIFIED
if (apiType == kUnityGfxRendererOpenGLCore || apiType == kUnityGfxRendererOpenGLES30)
{
s_CurrentAPI.reset( CreateRenderAPI_OpenGLCoreES(apiType) );
}
#endif // if SUPPORT_OPENGL_UNIFIED
}
注意:(NB:)处理图形设备事件时,进行检查非常重要(When processing graphics device event, it is very important to check) s_CurrentAPI
为null,因为Unity可能会调用(for null, because Unity may call) OnGraphicsDeviceEvent()
与(with) kUnityGfxRendererNull
(这将导致未初始化任何渲染API),然后使用实际渲染器第二次调用它.我们将稍后讨论如何初始化特定的API,但现在让我们看一下图形插件需要导出的另一个函数:((which will result in no render API initialized) before calling it second time with the actual renderer. We will look at how to initialize the specific API little later, but now lets take a look at one more function that a graphics plugin needs to export:)
extern "C" UnityRenderingEvent UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventFunc()
{
return OnRenderEvent;
}
Unity调用此函数以查询发出此插件的render事件时调用的函数.该函数应声明如下:(This function is called by Unity to query the function that is called when render event for this plugin is issued. The function should be declared as follows:)
static void UNITY_INTERFACE_API OnRenderEvent(int eventID);
eventID
是传递给的整数(is the integer passed to) IssuePluginEvent()
在Unity方面.这是一个极简的Unity脚本调用本机渲染插件的样子:(on Unity side. This is what a minimalistic Unity script calling native rendering plugin may look like:)
public class UseRenderingPlugin : MonoBehaviour
{
[DllImport("GhostCubePlugin")]
private static extern IntPtr GetRenderEventFunc();
void OnRenderObject()
{
// Issue a plugin event with arbitrary integer identifier.
// The plugin can distinguish between different
// things it needs to do based on this ID.
// For our simple plugin, it does not matter which ID we pass here.
GL.IssuePluginEvent(GetRenderEventFunc(), 1);
}
}
渲染API初始化(Render API Initialization)
现在让我们谈谈插件为特定的低级图形API初始化所需采取的步骤.(Let’s now talk about the steps a plugin needs to take to initialize for a specific low-level graphics API.) CreateRenderAPI()
函数创建一个实例(function creates an instance of) RenderAPI_D3D11
,(,) RenderAPI_D3D12
, 要么(, or) RenderAPI_OpenGLCoreES
类,具体取决于渲染类型.顾名思义,它们处理特定的低级API.完整的源代码可以在(class, depending on the render type. As class names imply, they handle specific low-level API. Full source code can be found on) 的GitHub(GitHub) ,因此我不会在这里发布.(, so I am not going to post it here.)
对于每个低级API,Unity都会公开特定的接口((For every low-level API, Unity exposes specific interface () IUnityGraphicsD3D11
和(, and) IUnityGraphicsD3D12
是我们最感兴趣的),可以通过以下方式查询(are of main interest for us) that can be queried through) IUnityInterfaces
, 例如:(, for example:)
IUnityGraphicsD3D11* d3d11 = interfaces->Get<IUnityGraphicsD3D11>();
让我们仔细看一下API特定的接口.(Let’s take a closer look at API-specific interfaces.)
Direct3D11(Direct3D11)
对于Direct3D11渲染器,Unity公开(For Direct3D11 renderer, Unity exposes) IUnityGraphicsD3D11
允许插件获取指向D3D11设备的指针的接口.然后可以从设备请求立即上下文:(interface that allows the plugin get a pointer to D3D11 device. Immediate context can then be requested from the device:)
IUnityGraphicsD3D11* d3d = interfaces->Get<IUnityGraphicsD3D11>();
m_d3d11Device = d3d->GetDevice();
CComPtr<ID3D11DeviceContext> d3d11ImmediateContext;
m_d3d11Device->GetImmediateContext(&d3d11ImmediateContext);
这是应用程序发出D3D11渲染命令所需的全部.其他方法(This is all an application needs to issue D3D11 rendering commands. Other methods of the) IUnityGraphicsD3D11
界面允许应用程序访问Unity渲染缓冲区的内部D3D11对象或本机纹理对象.(interface allow application to get access to internal D3D11 objects of a Unity render buffer or a native texture object.)
OpenGL/GLES(OpenGL/GLES)
没有(There is no) IUnityGraphicsGL
界面可能不出所料.原因是在OpenGL/GLES中,所有内容都是内部全局状态,因此,实际上没有任何接口可以返回.要在GL模式下初始化插件,Unity只需调用(interface as one may expect. The reason is that in OpenGL/GLES, everything is an internal global state, so there is really nothing that an interface would be able to return. To initialize the plugin in GL mode, Unity just calls) OnGraphicsDeviceEvent()
从具有活动GL上下文的线程中删除.插件可以调用初始化自身所需的任何gl函数.(from the thread with active GL context. The plugin may call whatever gl function it needs to initialize itself.)
注意:(NB:)OpenGL模式最重要的事情是Unity使用了由不同线程初始化的多个GL上下文.结果是,(the most important thing about OpenGL mode is that Unity uses multiple GL contexts initialized by different threads. As a result,) OnRenderEvent()
可能无法从与同一线程中调用(may not be called from the same thread as) OnGraphicsDeviceEvent()
,这意味着无法在中初始化GL上下文特定对象,例如VAO,FBO和程序管道(, which means that GL context-specific objects such as VAO, FBO, and program pipelines cannot be initialized in) OnGraphicsDeviceEvent()
.(.)
Direct3D12(Direct3D12)
Direct3D12是最复杂的情况(毫不奇怪),Unity 2017.1.1f1公开了5个不同的接口版本.该仿真器当前支持版本2:(Direct3D12 is (not surprisingly) the most involved case, for which Unity 2017.1.1f1 exposes 5 different interface versions. The emulator currently supports version 2:)
UNITY_DECLARE_INTERFACE(IUnityGraphicsD3D12v2)
{
ID3D12Device* (UNITY_INTERFACE_API * GetDevice)();
ID3D12Fence* (UNITY_INTERFACE_API * GetFrameFence)();
// Returns the value set on the frame fence once the current frame completes or the GPU is flushed
UINT64(UNITY_INTERFACE_API * GetNextFrameFenceValue)();
// Executes a given command list on a worker thread.
// [Optional] Declares expected and post-execution resource states.
// Returns the fence value.
UINT64(UNITY_INTERFACE_API * ExecuteCommandList)(ID3D12GraphicsCommandList * commandList,
int stateCount, UnityGraphicsD3D12ResourceState * states);
};
该接口提供以下功能:(The interface exposes the following functions:)
GetDevice()
-返回指向D3D12设备的指针(- returns a pointer to D3D12 device)GetFrameFence()
-返回指向用于同步GPU执行的篱笆的指针(- returns a pointer to the fence used to synchronize GPU execution)GetNextFrameFenceValue()
-当当前帧完成或刷新GPU后,返回在框架上设置的值(- returns the value set on the frame fence once the current frame completes or the GPU is flushed)ExecuteCommandList()
-执行给定的命令列表(- executes a given command list)
模拟器(The Emulator)
总览(Overview)
Unity图形仿真器系统包含以下主要组件:(Unity graphics emulator system contains the following main components:)
- Unity图形界面仿真器((Unity graphics interface emulators ()
UnityGraphicsD3D11Emulator
,(,)UnityGraphicsD3D12Emulator
,和(, and)UnityGraphicsD3D11Emulator
),它们负责模拟统一的图形界面(() which are responsible for mimicking unity graphics interfaces ()IUnityGraphicsD3D11
和(and)IUnityGraphicsD3D12
).().) - 场景模拟器,负责模拟场景对象(例如RenderTexture).插件使用(Scene emulator that is responsible for simulating scene objects (such as RenderTexture). The plugin uses) 勤奋的引擎(Diligent Engine) 促进与API无关的跨平台图形对象管理.引擎通过适配器连接到Unity接口((to facilitate API-agnostic cross-platform graphics object management. The engine connects to Unity interfcaes through adapters ()
DiligentGraphicsAdapterD3D11
,(,)DiligentGraphicsAdapterD3D12
和(, and)DiligentGraphicsAdapterGL
).场景模拟器还调用特定于插件的功能,例如设置转换矩阵或时间.(). Scene emulator also calls plugin-specific functions such as setting transformation matrices or time.) - Unity插件.该插件通过Unity接口与模拟器(和Unity)通信.该插件通过以下方式连接到图形API(Unity plugin. The plugin communicates with the simulator (and Unity) through Unity interfaces. The plugin connectes to the graphics API through)
RenderAPI_D3D11
,(,)RenderAPI_D3D12
和(, and)RenderAPI_OpenGLCoreES
类.它还与场景通信以获取其他信息,例如当前时间和转换矩阵.(classes. It also communicates with scene to get other infromation such as current time and transformation matrices.) 系统图如下图所示.(The system diagram is shown in the image below.)
Unity图形模拟器(Unity Graphics Emulators)
Unity图形仿真器派生自(Unity graphics emulators are derived from) UnityGraphicsEmulator
下面的清单中显示的类,并且大多数实现的标准样板代码不值得在此处发布.(class shown in the listing below and mostly implement standard boilerplate code that is not worth posting here.)
class UnityGraphicsEmulator
{
public:
virtual void Release() = 0;
virtual void Present() = 0;
virtual void BeginFrame() = 0;
virtual void EndFrame() = 0;
virtual void ResizeSwapChain(unsigned int Width, unsigned int Height) = 0;
virtual bool SwapChainInitialized() = 0;
virtual bool UsesReverseZ()const;
virtual IUnityInterface* GetUnityGraphicsAPIInterface() = 0;
IUnityInterfaces &GeUnityInterfaces();
static UnityGraphicsEmulator& GetInstance() { return *m_Instance; }
void RegisterInterface(const UnityInterfaceGUID &guid, IUnityInterface* ptr);
IUnityInterface* GetInterface(const UnityInterfaceGUID &guid);
virtual UnityGfxRenderer GetUnityGfxRenderer() = 0;
void RegisterDeviceEventCallback(IUnityGraphicsDeviceEventCallback callback);
void UnregisterDeviceEventCallback(IUnityGraphicsDeviceEventCallback callback);
void InvokeDeviceEventCallback(UnityGfxDeviceEventType eventType);
private:
UnityGraphicsEmulator(const UnityGraphicsEmulator&) = delete;
UnityGraphicsEmulator(UnityGraphicsEmulator&&) = delete;
UnityGraphicsEmulator& operator = (const UnityGraphicsEmulator&) = delete;
UnityGraphicsEmulator& operator = (UnityGraphicsEmulator&&) = delete;
std::vector< std::pair<UnityInterfaceGUID, IUnityInterface*> > m_Interfaces;
static UnityGraphicsEmulator *m_Instance;
std::vector<IUnityGraphicsDeviceEventCallback> m_DeviceEventCallbacks;
};
每个仿真器都会返回相应的Unity图形界面.对于D3D11,代码如下所示:(Every emulator returns corresponding Unity graphics interface. In case of D3D11, the code is shown below:)
UnityGraphicsD3D11Impl* UnityGraphicsD3D11Emulator::GetGraphicsImpl()
{
return m_GraphicsImpl.get();
}
static ID3D11Device* UNITY_INTERFACE_API UnityGraphicsD3D11_GetDevice()
{
auto *GraphicsImpl = UnityGraphicsD3D11Emulator::GetGraphicsImpl();
return GraphicsImpl != nullptr ? GraphicsImpl->GetD3D11Device() : nullptr;
}
IUnityInterface* UnityGraphicsD3D11Emulator::GetUnityGraphicsAPIInterface()
{
static IUnityGraphicsD3D11 UnityGraphicsD3D11;
UnityGraphicsD3D11.GetDevice = UnityGraphicsD3D11_GetDevice;
return &UnityGraphicsD3D11;
}
UnityGfxRenderer UnityGraphicsD3D11Emulator::GetUnityGfxRenderer()
{
return kUnityGfxRendererD3D11;
}
值得一提的两种方法是(The two methods worth mentioning are) BeginFrame()
和(and) EndFrame()
顾名思义,它们在每帧的开头和结尾处都会调用,并执行一些特定于API的操作.(, which, as their names suggest, are called at the beginning and end of each frame and perform some API-specific actions.) BeginFrame()
设置默认的渲染目标和深度模板缓冲区,清除它们并设置视口.(sets the default render target and depth-stencil buffer, clears them and sets the viewport.) EndFrame()
对于D3D11和OpenGL/GLES情况不起作用,对于D3D12,它将渲染目标转换为当前兼容状态并丢弃帧资源.(does nothing for D3D11 and OpenGL/GLES cases, and for D3D12 it transitions render target to present-compatible state and discards frame resources.)
Unity场景模拟器(Unity Scene Emulator)
Unity场景包含许多不同的对象,并且在模拟器中复制所有对象既不实用也不有用.但是,确实需要在仿真环境中复制某些对象(例如,示例项目中的镜像RenderTexture).由于仿真器支持多个低级API,因此,如果直接使用低级API,则有必要以多种方式实现场景对象.为避免此问题,场景模拟器使用(Unity scenes contain lots of different objects and duplicating all of them in the emulator is neither practical nor useful. However, some objects do need to be duplicated in the emulation environment (such as mirror RenderTexture in our example project). Since the emulator supports multiple low-level APIs, it would be necessary to implement scene objects in multiple ways if the low-level APIs were used directly. To avoid this problem, scene emulator uses) Diligent Engine,一个跨平台的图形API抽象库(Diligent Engine, a cross-platform graphics API abstraction library) . Diligent Engine通过适配器连接到Unity接口((. Diligent Engine connects to Unity interfaces through adapters () DiligentGraphicsAdapterD3D11(DiligentGraphicsAdapterD3D11) ,(,) DiligentGraphicsAdapterD3D12(DiligentGraphicsAdapterD3D12) 和(, and) DiligentGraphicsAdapterGL(DiligentGraphicsAdapterGL) ),以处理所有特定于API的功能.然后可以以图形API无关的方式创建所需的场景对象(请参见() that handle all API-specific functionality. The required scene objects can then be created in a graphics API-agnostic way (see) GhostCubeScene.cpp(GhostCubeScene.cpp) 例如).(for example).)
源代码(Source Code)
模拟器的(The emulator’s) 完整的源代码(full source code) 在GitHub上可用,并且可以免费使用.回购包含(is available at GitHub and is free to use. The repo contains) 示例Unity项目(sample Unity project) 它使用本机插件在镜像中渲染幽灵立方体的反射:(that uses native plugin to render reflection of a ghost cube in the mirror:)
模拟器使用场景模拟器创建渲染纹理,并使用相同的本机插件渲染立方体:(The emulator creates a render texture using the scene emulator and uses the same native plugin to render the cube:)
多维数据集仅在镜像中可见的主要原因是显而易见的,因为它是虚幻的多维数据集.另一个原因是在D3D12模式下,我不知道要获取主后缓冲区的渲染目标视图.可以在D3D11和OpenGL/GLES中执行此操作,但是我希望所有API上的企鹅看起来都一样.同时,Unity提供对渲染纹理的本机句柄的访问,这允许将其设置为D3D12插件中的渲染目标.(The main reason why the cube is only visible in the mirror is obviously because it is a ghost cube. The other reason is that in D3D12 mode, there is no way that I am aware of to get the render target view of the main back buffer. It is possible to do this in D3D11 and OpenGL/GLES, but I wanted the plguin to look the same on all APIs. At the same time, Unity provides access to native handle of a render texture, which allows to set it as render target in D3D12 plugin.) 的(The)**统一插件(unityplugin)**文件夹的组织方式如下:(folder is organized as follows:)
- **UnityEmulator(UnityEmulator)**文件夹包含主要仿真器组件的实现(Unity图形仿真器,Diligent Engine适配器,基本场景仿真器,特定于平台的功能)(folder contains implementation of the main emulator components (Unity graphics emulators, Diligent Engine adapters, base scene emulator, platform-specific functionality))
- **GhostCubeScene(GhostCubeScene)**文件夹包含场景特定对象的实现(RenderTexture)(folder contains implementation of the scene-specific objects (RenderTexture))
- **GhostCubePlugin/PluginSource(GhostCubePlugin/PluginSource)**文件夹包含本机插件的实现,该插件使用Diligent Engine渲染多维数据集(folder contains implementation of the native plugin that renders the cube using Diligent Engine)
- **Ghost Cube插件/Unity项目(GhostCubePlugin/UnityProject)**文件夹包含Unity项目(folder contains Unity project)
- **建立(build)**文件夹包含适用于Windows桌面和通用Windows平台的Visual Studio解决方案文件(folder contains Visual Studio solution files for Windows Desktop and Universal Windows platforms)
建立和运行(Building and Running)
Windows桌面(Windows Desktop)
要为Windows桌面平台构建项目,请在以下位置打开UnityUnityPlugin.sln解决方案(To build the project for Windows Desktop platform, Open UnityPlugin.sln solution in)**unityplugin/build/Win32(unityplugin/build/Win32)**文件夹,选择所需的平台和配置,然后构建项目.选择(folder, select the desired platform and configuration, and build the project. Select)GhostCubeScene(GhostCubeScene)作为启动项目并运行它.您可以使用(as startup project and run it. You can use)模式=(mode=){({)GL(GL)|(|)D3D11(D3D11)|(|)D3D12(D3D12)}命令行参数来选择图形API.(} command line argument to select the graphics API.)
通用Windows平台(Universal Windows Platform)
要为Windows桌面平台构建项目,请在以下位置打开UnityUnityPlugin.sln解决方案(To build the project for Windows Desktop platform, Open UnityPlugin.sln solution in)**unityplugin/build/Win32(unityplugin/build/Win32)**文件夹,选择所需的平台和配置,然后构建项目.(folder, select the desired platform and configuration, and build the project.)
安卓系统(Android)
要针对Android进行构建,您需要首先为Android开发设置机器.(To build for Android, you will need to first setup you machine for Android development.) 导航(Navigate to)**/unityplugin/GhostCubeScene/build/Win32/(/unityplugin/GhostCubeScene/build/Win32/)**文件夹并运行android_build.bat(folder and run android_build.bat)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C++ Windows DirectX Unity Unity3D OpenGL 3D game 新闻 翻译