为Unity3D编写Low-level Native Plugin(OpenGL Renderer Plugin)作渲染

为Unity3D编写Low-level native plugin插件,主要是用作对Unity自带的render pipeline作拓展使用,可以在其渲染的各个stage插入用户自己的渲染代码。

具体的编写过程与之前的Native Plugin编写差不多,也是用extern "C"对C++代码进行封装,然后导出dll。但是对于renderer plugin来说,有几个接口是必须要定义的,就如同Unity Documentation上说的那样。这几个接口的头文件可以在Unity安装文件夹的Editor子文件夹下面的某个子文件夹下面。在写自己的renderer plugin的时候,要把这些头文件给包含到项目中。这几个必须的接口为:

1、void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces);

2、void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload();

顾名思义,就是Plugin的加载和卸载。

在这两个函数中,我们可以对自己的Opengl renderer进行初始化、资源创建及资源销毁等操作。

注意:1、在Unity提供的实例中,OpenGL的部分采用的是静态编译的形式,而我之前采用的一直是动态编译的形式。

   2、我在实验Unity提供的实例的过程中,把所有的源文件转移到我自己的项目中,编译出来的dll在Unity中却完全没有效果。采用Visual Studio自带的dumpbin工具对dll导出的符号进行了一番对比之后,发现我的项目导出的符号与Unity示例项目导出的符号有出入,例如,Unity导出的符号为UnityPluginLoad = _UnityPluginLoad@0, 而我的项目导出的为_UnityPluginLoad@0 = _UnityPluginLoad@0,即导出的符号与实际函数的名字并不完全一样,那么在Unity的manged code中,dllimport导入的默认EntryPoinit就会不一样,如果不做特殊处理,假设都是声明如下:

[DllImport("PluginName")]

public static extern UnityPluginLoad(...)

那么我的项目的dll应该就找不到对应函数的入口,所以就不起作用。 后来我发现,示例项目采用了Module Defination文件对dll导出的符号进行设设置。我在我的项目文件中也创建了对应的.def文件,并在项目-属性-Linker-Input中对应的条目进行设置之后,重新build得到的dll用dumpbin查看之后,就跟示例工程中的一样了。

那么接下来,如何在Unity的Manged Code中编写代码将我自己的Render Code插入到Unity Pipeline中呢? 有两种方式:

1、CommandBuffer。查询Unity Documentation发现,Commandbuffer的描述为:List of graphics commands to execute.其中有一个函数为IssuePluginEvent,接收一个IntPtr callback参数和一个int eventID参数,该函数可以将一个进行渲染的回调函数加入到渲染命令Buffer。然后怎么将这个CommandBuffer加入到render pipeline的对应Stage呢?答案在Camera和Light类中,这两个类中都有一个名为AddCommandBuffer的函数,以Camera为例,有一个类型为Rendering.CameraEvent的参数和一个类型为Rendering.CommandBuffer的函数。第二个参数一目了然,第一个参数是一个enum类型,这里面有相机在渲染pipeline各个阶段的enum。

2、GL.IssuePluginEvent. 具体参数看文档吧,布罗啰嗦了。这个函数没说在啥阶段,你可以把这个函数放在Camera.OnpostRender函数中,然后对应的渲染就在对应的时刻进行。

 

那个渲染的回调函数也要按照Unity给的接口在严格实现,具体接口在那些头文件里有,就是:

void UNITY_INTERFACE_API UnityRenderingEvent(int eventID).

值得注意的另外一点是,原生OpenGL世界坐标系是右手坐标系,但是Unity中的世界坐标系是左手坐标系。因此,在从Unity中向Native Renderer Plugin中传递世界坐标系中的位置和方向数据时,要注意对x轴的值取反(乘以-1)。

原文地址:https://www.cnblogs.com/chandler00x/p/6264274.html