前言
小时候最喜爱看西游记,总是空想着本人能像孙悟空那样,脚踏筋斗云穿梭云海间,生存在仙境中。长大后做了图形程序,始终想做一个真正的云海进去,但因为挪动端的计算瓶颈,始终没能做出一个兼顾性能和成果的体积云(体积云是基于物理的云渲染零碎,在游戏中模拟出具备半透明、无规则的体现成果的云)。
自己是一个游戏开发爱好者,常常会 fellow 一些前沿的技术,并且将一些感兴趣的技术点开发成一个能够方便使用的插件。最近看到华为 HMS Core 中的 CGKit 提供了一个体积云插件,所以就花了两天工夫依照官网文档集成到 Unity 中,下图是一个简略场景的成果(下面的云为天空盒,上面的云为集成后的体积云),能够看到体积云整体偏实在,“金边”成果也比拟显著,反对动静光照,能够在云中任意穿梭。最重要的是我在一个低端机(光荣 8 青春版)上测试了一下性能,分辨率为 720P 的状况下,居然能够跑到 50 帧!该插件还有一个有意思的性能是,反对开发者定制云的形态,这样我就能够领有一朵任意形态的云了。
接下来就和大家分享一下我是如何将 HMS CGKit 体积云插件集成到 Unity 中的,心愿对大家的开发有所帮忙。
2、开发筹备
1、Visual Studio,举荐应用 2017 及以上版本;
2、Android Studio,举荐应用 4.0 及以上版本;
3、Unity,举荐应用 2018.4.12 及以上版本;
4、EMUI 8.0 及以上华为手机或 Android 8.0 及以上非华为手机;
5、下载 SDK
到华为开发者联盟下载 SDK,下载链接及阐明文档链接如下:
SDK 下载链接:https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Library-V5/sdk-download-0000001050441521-V5
开发指南:https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/development-preparations-0000001076931602
API 参考:https://developer.huawei.com/consumer/cn/doc/development/HMSCore-References-V5/overview-0000001077661506-V5
将 SDK 下载下来,目录构造如下:
process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDcwODI0MA==,size_16,color_FFFFFF,t_70)
通过官网的阐明文档可知:RenderingVolumeCloud.dll 是基于 OpenGL 的 PC 端调试插件,libRenderingVolumeCloud.so 是基于 OpenGLES30 的 Android 端插件,assets 目录下的两个 bin 文件是渲染体积云时须要用到的资源文件,include 目录下的头文件是该插件的接口定义。
3 开发具体记录
因为该体积云插件对外裸露的是 C ++ 接口,所以要想集成到 Unity 中,须要将其封装为 Unity 的原生插件(Native plugin),而后集成到 Unity 取得体积云的渲染后果。上面别离给大家介绍一下我的集成过程。
3.1 原生插件的封装
Unity 原生插件是指用 C、C++、Objective-C 等编写的原生代码库,插件容许游戏代码(用 Javascript 或 C# 编写)调用这些库中的函数。Unity 原生插件的封装能够参照如下官网文档以及官网示例教程:
文档:https://docs.unity3d.com/Manual/NativePluginInterface.html
代码:https://github.com/Unity-Technologies/NativeRenderingPlugin
依据 Unity 官网示例,须要别离编译 so 和 dll 作为动态链接库供 Unity 调用。能够别离用 Visual Studio 和 Android Stuido 间接对官网公布的开源代码进行批改,集成体积云渲染性能,并编译出对应的库文件,上面简要介绍批改形式。
RenderingPlugin.def 文件中的函数就是原生插件裸露给 Unity 的接口,其具体实现在 RenderingPlugin.cpp 中。咱们保留 RenderingPlugin.cpp 中的 UnityPluginLoad、UnityPluginUnload、OnGraphicsDeviceEvent、OnRenderEvent 和 GetRenderEventFunc 这几个 Unity 原生插件必须的函数以及相干的动态全局变量,并增加了 3 个接口(ReleaseSource,BakeMultiMesh,SetRenderParasFromUnity),如下图所示。
接下来通过对官网源代码批改,利用这几个接口实现对 CGKit 体积云插件的调用。批改如下:
(1) 批改 OnGraphicsDeviceEvent 函数。当 eventType 为 kUnityGfxDeviceEventInitialize 时,调用 CGKit 体积云插件 CreateRenderAPI 函数创立 RenderAPI 类型的变量,并调用 RenderAPI.CreateResources() 函数;当 eventType 为 kUnityGfxDeviceEventInitialize 时 delete RenderAPI 类变量。
(2) 批改 OnRenderEvent 函数。将 SetTextureFromUnity 函数中设置的全局动态变量作为参数,在该函数中间接调用 RenderAPI. RenderCloudFrameTexture() 函数。
(3) 定义 SetTextureFromUnity 函数。将 RenderAPI. RenderCloudFrameTexture() 函数所需的 4 个输出值传给定义好的动态全局变量,不便当前间接调用该函数进行体积云渲染。
(4) 定义 SetRenderParasFromUnity 函数。在该函数中调用 RenderAPI. SetRenderCloudParas() 函数。
(5) 定义 ReleaseSource 函数。在该函数中调用 RenderAPI. ReleaseData() 函数。
为了实现云状态的定制,PC 端插件须要集成体积云的烘焙性能,所以 dll 要比 so 多一个烘焙接口。在编译 dll 时须要额定定义 BakeMultiMesh 函数,首先调用 CreateBakeShapeAPI 创立 BakeShapeAPI 类变量,而后调用 BakeShapeAPI.BakeMultiMesh() 函数进行烘焙。
3.2 集成到 Unity
原生插件封装胜利后,就能够失去适配 Unity 和该体积云插件的 libUnityPluginAdaptive.so 和 UnityPluginAdaptive.dll。接下来就是新建一个 Unity 3D 工程,来实现体积云性能的调用,这里我实现了 ARM64 版本,以此为例给大家介绍一下。
将 ARM64 版本的 libUnityPluginAdaptive.so、libRenderingVolumeCloud.so、UnityPluginAdaptive.dll 和 RenderingVolumeCloud.dll 放到 Assets/Plugin/x86_64 文件夹下,没有该文件夹的话本人新建一个就好。须要对两个 so 和 dll 别离进行如下配置:
因为该体积云插件的 PC 端调试插件是基于 OpenGL 的,所以须要做如下设置:
因为该体积云插件的 Android 端插件是基于 OpenGLES30 的,所以须要做如下设置:
该插件还提供了两个 bin 文件,将这两个文件放到工程任意文件夹下,只有在传入参数中定义好对应的门路即可,其中 noise.bin 是体积云的细节噪声,shape.bin 是体积云的三维形态纹理。也能够调用插件的 BakeMultiMesh 接口自定义体积云的状态,这一部分会在前面具体开展,先临时应用插件提供的三维形态纹理。
3.3 实时渲染体积云
调用体积云插件前,须要增加打点性能依赖 jar 包,能够通过批改代码工程的利用级 build.gradle 文件来实现,任意 jar 包版本号均可。
将下载后的 jar 包,拷贝到 Unity 工程中,Assets/Plugin/Android/bin 文件夹下,没有该文件夹的话本人新建一个就好。
接下来就能够编写 C# 脚本调用相干接口,这里我显式调用的适配层接口如下:
(1) SetTextureFromUnity 函数的作用是设置 cloudTexture 的指针、depthTexture 的指针,以及 cloudTexture 的尺寸。其中 cloudTexture 是用于体积云绘制的纹理数据,depthTexture 是有以后帧 depth 数据的纹理。该函数只需执行一次即可。
(2) SetRenderParasFromUnity 函数的作用是调用 CGKit 体积云插件参数设置的接口,设置体积云的参数。因为这些参数每一帧都要更新,所以该函数每帧都要执行一次。
(3) GetRenderEventFunc 函数的作用是调用 CGKit 体积云插件绘制接口,将体积云绘制到 cloudTexture 上。该函数的调用形式为 GL.IssuePluginEvent(GetRenderEventFunc(), 1),也能够以 CommandBuffer 的模式调用 commandBuffer.IssuePluginEvent (GetRenderEventFunc(), 1)。每帧都要执行一次。
(4) ReleaseSource 函数的作用是调用 CGKit 体积云插件开释资源接口。只须要最初调用一次即可。
接口定义好当前,调用流程如下:
上图中灰色的局部是须要依据咱们本人来实现的,这里给大家介绍一下我的一个简略实现。在调用渲染接口之前,须要创立两个 RenderTexture,其中一个用来保留体积云插件渲染后果,另外一个用来保留 depth。而后调用 SetTextureFromUnity 接口,将两个 RenderTexture 的 NativeTexturePtr 以及尺寸作为输出参数,这样前面就能够失去体积云渲染的后果。
在 Update 阶段,须要更新体积云插件的构造体参数,该参数须要参考 CGKit 体积云插件包 include 目录下 VolumeRenderParas.h 文件,在 C# 脚本中须要定义同样的构造体。参数具体含意能够参考 CGKit 体积云插件阐明文档,须要留神的是构造体要一字节对齐,构造体中示意矩阵的 4 个数组采纳行优先排列。下图是一个简略的示例:
更新构造体变量后,调用 SetRenderParasFromUnity 接口以援用的形式传递体积云渲染的参数,之后的渲染就会基于这组参数进行。
调用渲染接口时,咱们以 OnRenderImage 后处理的模式将体积云绘制到屏幕上,当然也能够应用 CommandBuffer 的模式在其余阶段进行配置。在 OnRenderImage 阶段,首先要将 depth 绘制到之前创立的 depthTexture RT 上,而后调用 GL.IssuePluginEvent(GetRenderEventFunc(),将体积云绘制到之前创立的 cloudTexture RT 上,最初将 cloudTexture 和 OnRenderImage 的输出 src 利用透明度交融到 dst 上,就能够在屏幕上显示体积云。
3.4 打包 APK 到手机端验证
在 PC 端调试好成果之后,就能够间接打包到 APK 进行 Android 端验证。Android 端和 PC 端惟一的区别就是构造体参数中的两个字符串数组,别离是 shape.bin 和 noise.bin 文件的门路,这两个门路须要在不同平台辨别开来,能够将两个 bin 文件放到 Application.persistentDataPath 文件夹下。
3.5 烘焙三维形态纹理
该体积云插件同时也提供了烘焙接口,能够自定义三维形态纹理。同样将其集成到适配层,前边曾经有过介绍,接口函数为:
函数的输出为 BakeData 构造体变量以及保留 bin 文件的门路,同时会生成相似于 shape.bin 的文件,其中 savePath 需蕴含残缺门路以及后缀 (.bin)。因为数组长度不定,所以该构造体的成员变量为数组指针类型和 int 型,参数具体含意能够参考 CGKit 体积云插件阐明文档。依据阐明文档咱们能够晓得,烘焙接口的作用是将一个 Boundingbox 内的多个 mesh 烘焙为三维形态纹理。Boundingbox 的大小由构造体内的两个参数决定,别离为 minBox 和 maxBox。
如下图所示,调用接口前,先将多个三维模型组合到一起。为了可视化到底哪些区域是可烘焙区域,咱们能够在空间中依据 minBox 和 maxBox 这两个参数绘制一个线框,在线框外的区域是不予烘焙的。调整好各个模型的地位之后,就能够调用该接口进行烘焙。
在烘焙时还须要留神的一点是,烘焙好的三维形态纹理在渲染体积云时会被间断采样,所以安排三维模型时,须要在程度的四个与 boundingBox 相交的地位上搁置雷同的三维模型,使其被循环采样时放弃连续性。
烘焙完结之后就能够应用自定义的三维形态纹理进行体积云渲染,用法与官网提供的 shape.bin 用法一样。
Demo 获取
emo 以 unitypackage 的模式打包并上传至百度云盘,地址请戳:
https://pan.baidu.com/s/1JEt_… 提取码: yx8a
从 Assets->Import Package->Custom Package 中导入该 unitypackage,其中 Plugin 文件夹中有适配层和 CGKit 体积云插件的 dll 和 so。volumeCloud 文件夹中有相干的脚本、shader 以及搭建的场景。StreamingAssets 文件夹中寄存了相干的资源文件 (shape.bin 和 noise.bin)。volumeCloud/Readme.txt 中注明了 Demo 运行的一些注意事项,在运行前请按阐明进行配置。
原文链接:https://developer.huawei.com/consumer/cn/forum/topic/0202500645526020389?fid=18
原作者:转来转去