相关文章推荐
讲道义的茶叶  ·  mysql count ...·  3 月前    · 
爱玩的感冒药  ·  插入 ...·  8 月前    · 
Unity HDRP室外场景打光流程分享(上篇)UE4场景转Unity HDRP场景

Unity HDRP室外场景打光流程分享(上篇)UE4场景转Unity HDRP场景

0 概述:

某天在ArtStation上看到一个名为The Rally Point(集结点)的高质量场景素材,以下是链接: artstation.com/marketpl

这位作者是前育碧的环境艺术家Guillaume Hecht,作品灵感来自Gears of War(战争机器),图1是来自原作的渲染:

图 1 原作渲染图

自Unity HDRP(高清渲染管线)在Unity 2019.3版本正式发布以来,我一直想找一个场景来做HDRP打光流程的教程,所以看到这个场景以后就觉得特别合适。不过作者放在ArtStation市场里提供购买的版本是UE4项目文件,因此我需要花点时间把这个UE4场景转到Unity中。因为UE4和Unity的开发环境很不一样,所以我觉得把整个转的过程记录下来,分享给广大开发者可能会蛮有意思的,也可能帮到想把UE4项目转到Unity HDRP中的开发者。

我将会通过两篇文章来详细介绍整个转项目的过程,本文是上篇,描述以下1到7的转换步骤:

1) 从UE4中导出模型和纹理

2) 新建Unity HDRP项目

3) 将模型和纹理导入Unity中

4) 在Unity中创建HDRP材质

5) 在Unity中创建所有预制体(Prefab)

6) 在UE4中使用蓝图导出场景模型摆放信息到文本

7) 在Unity中使用自定义脚本读取摆放信息文本重建场景

8) Unity HDRP打光实践(这一部分将会在本文的下篇中详细讲解)

1 资产转换详解

1.1 从UE4中导出模型和纹理:

1.1.1 导出模型: 在Content Browser中选择包含所有模型的文件夹,选中所有模型。然后鼠标右键点击,在弹出菜单中选择Asset Actions中的Bulk Export菜单,最后在FBX Export Options窗口选择如图2中的选项进行模型导出。导出顺利完成,没有任何报错信息。

图 2 UE4的模型导出界面

1.1.2 导出纹理: 在Content Browser中选择包含所有纹理的文件夹,选中所有纹理。然后鼠标右键点击,在弹出菜单中选择Asset Actions中的Bulk Export菜单,选择一个文件夹保存导出的纹理。导出423个纹理完成以后,UE4显示了图3中的72条报错:

图 3 UE4纹理导出时的报错信息

我将会在后面的模型和纹理处理步骤介绍相应的修复方法。

1.2 新建Unity HDRP项目:

现在我们要新建一个Unity项目用于导入上述模型和纹理资源。通过Unity Hub界面新建一个HDRP项目,如图4所示:

图 4 通过Unity Hub创建一个HDRP项目

创建完成以后,项目中默认会有一个SampleScene,如图5所示。你可以通过这个示例工程学习HDRP提供的光照,材质和后处理功能。如果你想全面了解这个示例场景,也可以观看我之前制作的讲解视频,在Unity中文课堂上可以找到: learn.u3d.cn/tutorial/u

图 5 默认的HDRP模板项目场景

1.3 将模型和纹理导入Unity中:

把之前从UE4中导出的模型和纹理文件夹,直接拖入Unity编辑器的Project窗口中完成整个导入过程。

1.3.1 处理导入的模型:

虽然UE4和Unity都是左手坐标系,但是UE4里X轴朝前,Z轴朝上;Unity里Z轴朝前,Y轴朝上。

为了解决这个坐标系问题,我们可以在Unity的Project窗口中选择所有模型,在模型导入界面选择Bake Axis Conversion选项,这会自动把所有模型改成Z轴朝前,Y轴朝上,具体界面选项如图6所示。

图 6 模型导入界面上的Bake Axis Conversion选项

例如,在应用Bake Axis Conversion这一选项之前,图7中显示的导入Unity的模型为X轴朝前,Z轴朝上:

图 7 UE4的坐标系

应用Bake Axis Conversion选项之后,模型的坐标系如图8所示:

图 8 Unity中应用了Bake Axis Conversion选项以后的模型坐标系

1.3.2 处理导入的纹理:

1.3.2.1 第一个需要处理的是之前在导出纹理时出现的报错信息:Texture is RGBA16 and cannot be represented at such high bit depth in .tga. Color will be scaled to RGBA8。通过网络搜索论坛发现在这是UE4的一个未修复bug,解决方法是对出现这种报错的纹理做如下处理:在Photoshop或者任何图形编辑软件中把R通道和B通道互换一下。

1.3.2.2 第二个需要处理的问题是后缀为_ORM的纹理,如图9所示。

图 9 需要做进一步处理的纹理

上述每一个纹理中的三个通道中分别包含了Ambient Occasion环境光遮蔽(红色通道),Roughness粗糙度(绿色通道),Metallic金属度(蓝色通道)三张纹理。这被称为Channel-Packed Textures(通道打包纹理)。通过这样的方式,我们可以在同一张纹理中保存多张代表不同材质属性的灰度贴图。这不仅节省了内存空间,还可以让渲染器通过单次纹理获取来采样这些使用相同UV坐标的灰度贴图,从而提高游戏运行性能。

在Unity HDRP中,我们也可以使用通道打包的纹理,这种贴图成为Mask Map(遮罩贴图)。Unity HDRP的Mask Map的四个通道如表格1所示分别保存以下信息:

表格 1 Unity HDRP的Mask Map中各个通道保存的灰度贴图信息

颜色通道 贴图
红色 Metallic(金属度)
绿色 Ambient
Occlusion(环境光遮蔽)
蓝色 Detail
Map Mask(细节贴图遮罩)
Alpha Smoothness(平滑度)

因为Mask Map在不同通道中保存的内容不同,所以在把后缀为_ORM的纹理转换成Mask Map时,我们需要在Photoshop的通道编辑界面进行手动操作,具体操作如图10所示。

图 10 UE4的通道打包纹理转成Unity的通道打包纹理(Mask Map)

对于图10的具体说明如下:

l Occlusion贴图:直接从红色通道拷贝到绿色通道。

l Roughness贴图:在UE4中,此贴图保存的是表面的粗糙度信息,黑色代表数值0(最光滑),白色代表数值1(最粗糙)。但是Unity中这张图代表的却是光滑度,也就是黑色代表数值0(最粗糙),白色代表数值1(最光滑)。因此在拷贝之前,我们要用Photoshop的Invert功能把贴图做个反转,然后再从绿色通道拷贝到Alpha通道。

l Metallic贴图:直接从蓝色通道拷贝到红色通道。

l 这里我们不会使用蓝色通道,因为此项目中并没有使用细节贴图(Detail Map)。

1.4 在Unity中创建HDRP材质

处理完模型和纹理,接下去我们来创建材质。目前并没有任何自动化的方法来完成材质的转换,因此我们必须手工来做这件事情。

Unity在HDRP中提供了非常丰富的材质选择,不过通常我们使用默认Lit着色器就可以模拟大多数的材质效果。在当前项目中还有一些材质并不能用默认的Lit着色器来制作,所以我用了Unity的Shader Graph对比UE4中的材质编辑器所用的节点来完成制作。

下面我们使用两个示例来具体描述如何使用Lit着色器和Shader Graph来为模型制作相关的材质。

1.4.1 使用Lit着色器制作材质:

1.4.1.1 选择模型,在模型导入界面选择Materials选项,使用Extract Materials…按钮把包含在模型中的材质信息解出,如图11所示:

图 11 通过模型导入界面解出材质信息

1.4.1.2 模型中的材质解出以后,Unity会使用Lit着色器自动生成相应数量和正确命名的材质,并关联到模型网格上,如图12所示:

图 12 解出的材质信息自动关联到模型

1.4.1.3 我们来查看M_Metallic_Trim_03这个材质的参数面板,如图13所示。可以看到Base Map,Mask Map和Normal Map都为空,没有自动关联正确的纹理。

图 13 解出的材质使用默认的HDRP Lit材质,但是并不会关联正确的纹理

这时我们要回到UE4中,选择SM_Alley_6x5m这个网格,然后打开材质编辑器查看它上面M_Metallic_Trim_03材质是如何配置的,如图14所示。我们可以在UE4的材质编辑器中看到每个参数是如何连接的,也能查看到连接的是哪个纹理。

图 14 UE4中的标准材质设置图

通过对UE4和HDRP的Lit材质界面的对比,可以发现在参数命名上两者的区别只有一个Roughness(UE4)和Smoothness(Unity)。因为我们在处理纹理的时候已经完成了相关的操作(通过Photoshop的Invert功能把UE4中的Roughness贴图反转成了可以在HDRP中使用的Smoothness贴图),所以我们可以把相关纹理直接与Lit材质上的参数相关联。

对于M_Metallic_Trim_03这一类可以用HDRP默认Lit材质模拟效果的,我们可以按照上面描述的步骤,逐个完成材质的转换。

下面我们看一下需要使用Shader Graph来手动处理的材质。

1.4.2 使用Shader Graph制作自定义材质:

1.4.2.1 我们回到UE4编辑器,找到MI_Cobblestone_01这个材质并打开材质编辑器,发现它使用了一个名为MM_Cobblestone_01的自定义着色器,如图15所示:

图 15 UE4中使用自定义着色器的材质

它的设置蛮复杂的,如图16所示:

图 16 其中一个比较复杂的自定义材质

不过研究完了其实也不是那么复杂,里面主要用到的一个节点是UE4内置的ParallaxOcclusionMapping节点,如图17所示:

图 17 UE4中的ParallaxOcclusionMapping节点

而在Unity的Shader Graph中也有一个相同的内置节点,如图18所示:

图 18 Unity中的ParallaxOcclusionMapping节点

因此我们可以按照UE4里面的连接方式,在Shader Graph里面完成自定义着色器的制作。最终完成的Shader Graph着色器如图19所示:

图 19 Unity中使用Shader Graph参照UE4的着色器完成自定义着色器的制作

1.4.2.2 本项目中的其他自定义着色器也可以用相同的方式处理完成。整个项目一共有16个自定义着色器。

1.5 在Unity中创建所有预制体(Prefab):

完成了所有模型和纹理的处理以后,我们就可以把每个模型制作成预制体(Prefab)了。制作Prefab的方式非常简单,此处不再赘述。图20中显示的是所有制作完成的Prefab。

图 20 Unity中所有制作完成的模型Prefab

完成所有Prefab的制作以后,在Project窗口根目录下创建一个Resources文件夹,把所有Prefab放入此文件夹中,如图21所示。

图 21 将所有Prefab放入Resources文件夹中

此项目为了装饰场景,也大量使用了贴花(Decal)。HDRP支持创建贴花。贴花可以为场景提供可用于灵活摆放且性能高效的小细节,比如墙上和地板上的污渍,地上的树叶,纸片等。我把这些贴花Prefab放在了Resources文件夹下的Decal_Prefab文件夹下。

把所有Prefab放入Resources文件夹中的目的是为了便于后续用脚本自动摆放场景中物体时,我们可以快速方便地获取这些Prefab用于场景的重建。

1.6 在UE4中使用蓝图导出场景模型摆放信息到文本:

通过上述步骤,我们已经在Unity中获得了全部的模型,纹理和正确设置的材质。我们也将这些模型制作成了可以用于搭建场景的Prefab。理论上我们可以对照UE4中的场景,在Unity中手工搭建完成整个场景了。

不过对于拥有几千个物体组件的场景,手工搭建将会耗费大量时间。因此,我们要用程序化的方式来完成Unity中的场景搭建工作,基本步骤如下:

1. 使用蓝图(Blue Print)可视化编程的方式,将场景中指定物体的名称,所关联的模型网格名称,位置,旋转和大小信息,保存在纯文本中。

2. 纯文本中每一行保存一个物体的信息,数据之间用一个空格分隔。

3. 在Unity中用脚本读取这个纯文本,使用Resources文件夹中保存的Prefab生成整个场景并保存。

4. 重复上述操作直到所有类别的物体在场景中完成重建。

通过对UE4场景的分析,我决定将场景中的物体分成三类:静态物体,通过蓝图(Blue Print)保存的物体(UE4中的蓝图(Blue Print)与Unity中的预制体(Prefab)类似),贴花(Decal)。我为这三类物体创建了三个蓝图用于导出三个文本,以下分别为可以将三类物体信息导出到纯文本的蓝图(三个蓝图文件可在附件中下载)。(注:以下蓝图中包含来自Victory Plugin的节点,此UE4插件可以在此下载: forums.unrealengine.com

l 导出静态物体(图22):

图 22 用于导出所有静态物体相关信息的蓝图

l 导出用蓝图保存的物体(图23):

图 23用于导出所有使用蓝图保存物体相关信息的蓝图

l 导出贴花(图24):

图 24 用于导出所有贴花相关信息的蓝图

图25是导出的静态物体的信息纯文本示例:

图 25 导出的静态物体的相关信息

1.7 在Unity中使用自定义脚本读取摆放信息文本重建场景:

有了导出的纯文本以后,我们就可以在Unity中用脚本来读取这些信息,然后在场景中快速重建场景了。

这里我们使用的是Unity的编辑器API,因此在脚本中要使用UnityEditor相关的命名空间。我在附件中提供了三个脚本,用于分别处理三种类型的物体:静态物体(使用CreateStaticMeshObjects.cs),蓝图物体(使用CreateBPMeshObjects.cs)和贴花(使用CreateDecalObjects.cs)。注意:要让这些脚本工作,必须在Project窗口中创建一个名为Editor的文件夹,把这些脚本放到此文件夹中。

图26为CreateStaticMeshObjects.cs的脚本内容:

图 26 静态物体重建场景脚本

脚本逻辑解释如下:

1. MenuItem定义了一个菜单,让我们可以通过Unity编辑器的顶部菜单触发这个脚本。

2. 通过StreamReader的ReadLine方法读取放在Project窗口中根目录里的StreamingAssets文件夹中的纯文本,逐行读取文本内容放到相应的变量中。

3. 接着要定义一个Matrix4x4用于之后的坐标系转换操作。

4. 然后用PrefabUtility.InstantiatePrefab方法来生成正确的Prefab实例,并为此实例改名,应用坐标变换后的位置与旋转信息,以及大小信息。

5. 最后,使用EditorSceneManager.SaveScene方法保存生成好的场景。

上述操作完成以后,我们就获得了一个近乎完成的场景。以下视频演示了在Unity中运行上述三个编辑器脚本的实际效果:

编辑器脚本导入模型位置信息 https://www.zhihu.com/video/1396451617336545280

当然,要让这个场景能够完整用于项目中,我们还需要为它添加一些背景元素,补上原先没有那么完整的部分。

2 上篇结语:

通过上述步骤,我们成功地将一个UE4场景转成了一个Unity中支持HDRP高清渲染管线的场景。整个过程总结下来最费时间的是手工转所有的材质,其他步骤其实都可以很便捷地完成。

下一篇文章中,我将会使用重建好的场景,使用HDRP的光照系统制作白天和夜晚两种光照效果,具体效果如图27和图28所示:

图 27 白天光照效果
图 28 夜晚光照效果

图 28 夜晚光照效果

发布于 2021-07-08 12:55