zoukankan      html  css  js  c++  java
  • 为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)。

  • 相关阅读:
    Altium Designer如何从已有的PCB图中导出封装库
    获得内核函数地址的四种方法
    poj2976 Dropping tests
    poj3045 Cow Acrobats
    CF916C Jamie and Interesting Graph
    poj3104 Drying
    poj2455 Secret Milking Machine
    poj2289 Jamie's Contact Groups
    网络流最小路径覆盖
    CF897C Nephren gives a riddle
  • 原文地址:https://www.cnblogs.com/chandler00x/p/6264274.html
Copyright © 2011-2022 走看看