虚幻引擎是全球最先进的实时3D创作工具,可制作照片级逼真的视觉效果和沉浸式体验,2022年4月5号虚幻引擎发布了颠覆性的UE5。倾斜摄影是城市实景的基础,通过无人机采集实际照片再进行三维重建,常见的数据格式为osgb。本文主要介绍UE5如何导入OSGB。
UE5致力于带来前所未有的自由度、保真度和灵活性,帮助游戏开发者和各行各业的创作者创作新一代实时3D内容和体验。 这里简单介绍一下UE5颠覆性的技术。
Quixel Bridge现已完全集成到引擎中,你可以直接拖放和访问Megascans库中的所有资产。在新版“创建”菜单中,你可以获取内容,以及创建并放置Actor。
为了在视口中腾出更多空间,你现在可以轻松地展开和收合内容浏览器,并将任何编辑器选项卡停靠至侧边栏。此外,在“细节”面板中,你还可以更快捷地访问你要寻找的属性。
使用虚拟化微多边形几何体系统Nanite和全新的虚拟阴影贴图系统创建具有海量几何细节的游戏和世界。
你可以直接导入并复制由数百万个多边形组成的任何网格体,同时保持实时帧速率,无任何明显失真。
这些系统会智能地仅流送和处理你可感知到的细节,这在很大程度上放宽了对多边形计数和绘制调用的限制。
Lumen是一套完全动态的全局光照和反射解决方案,当场景中的直接光照或几何体发生变化时(如,太阳照射角度随当日时间而改变,或打开户外门),它将即时地对间接光照作出相应调整。
有了Lumen,你不再需要编辑光照贴图的UV并等待光照贴图的烘焙,也无需放置反射采集;就可以直接在编辑器内看到与主机上相同的效果。
次世代主机的玩家希望在高分辨率显示器上享受60FPS或更高的帧率,这为渲染资源带来了巨大的压力。
时序超级分辨率(TSR)是虚幻引擎内置的高质量上采样系统,具有平台独立性,通过它,引擎就能够以更低的分辨率进行渲染,但输出的像素保真度可接近以更高分辨率渲染的帧。
在虚幻引擎5中,全新的世界分区系统改变了关卡的管理和流送方式,它会自动将世界划分为网格,仅流送必要的单元格。
借助全新的“一Actor一文件”系统,团队成员现在还可以同时在同一个世界的同一个区域中工作;而通过数据层,你可以创建同一个世界的不同变体(例如,白天版本和夜间版本),变体将作为数据层存在于同一空间中。
UE5通过Datasmith插件可以支持非常多的数据格式,但是目前还不支持OSGB格式。所以我们的思路是将OSGB转成FBX格式,再导入UE5。
OpenSceneGraph提供了一个格式转换工具osgconv.exe,可以方便的将OSGB转成Fbx。
通过命令行工具即可生成fbx文件,如下:
osgconv infile.osgb outfile.fbx
不过考虑到我们的osgb文件通过比较多,我们可以通过python脚本来一键生成批处理命令,示例脚本如下:
import glob
osgPath = r'D:\work\OpenSceneGraph-3.6.5-VC2019-64-Release\bin'
infile = ""
for p1 in glob.glob('*'):
if(-1 != p1.find(".osgb")):
infile = infile + p1 + " "
cmdBat = "osgconv.exe " + infile+"../model/1.fbx"
file_path = 'data.bat'
with open(file_path, mode='w', encoding='ANSI') as file_obj:
file_obj.write('set path='+osgPath+'\n')
file_obj.write(cmdBat)
file_obj.write('\npause')
当OSGB文件没有PagedLOD时,上面的方法生成的fbx可以很好的导入UE5。但是当osgb里面有多层次细节的时候,我们会发现转成的文件会有重复的部分,即精细的部分和低精细的都会在fbx里面,从而导致模型不正确。
由于虚幻引擎自带Hlod系统,所以我们不需要PagedLod里面的非精细部分,即我们需要将低精度的模型去掉。
这里我们采用OpenSceneGraph的osgDB库进行处理,剔除掉低精度的模型。osgDB是官方提供的一个格式转换库,支持大量常见的2d和3d的图形文件格式的转换。由于这个库是C++开发的,我们采用CMake的方式进行组织代码。示例如下:
整个代码实现的逻辑为从每个文件的根节点开始遍历,当PagedLOD里面有两个模型(精细和非精细)时候,我们去掉非精细模型,保留精细部分。而当模型没有精细模型的时候,我们可以直接将这个文件删除。示例代码如下:
void handlePageLod(osg::PagedLOD *node)
{
auto size = node->getNumPriorityOffsets();
if (1 == size)
{
return;
}
if (2 == size)
{
//当为2的时候,说明有更精细的模型,可以删除当前child
auto childCount = node->getNumChildren();
if (1 == childCount)
{
node->removeChild(0, 1);
return;
}
cout << "error handlePageLod childCount != 1" << endl;
return;
}
else
{
cout << "error handlePageLod getNumPriorityOffsets >" << size << endl;
}
}
int main(int, char **arg)
{
std::cout << "Hello, world!\n";
string inpath = arg[1];
string outPath = arg[2];
std::cout << "inpath = " << inpath << endl;
std::cout << "outPath = " << outPath << endl;
auto root = osgDB::readNodeFile(inpath);
auto group = root->asGroup();
auto childNumber = group->getNumChildren();
std::vector delPageLod;
for (unsigned int i = 0; i < childNumber; i++)
{
auto pagedLod = dynamic_cast(group->getChild(i));
handlePageLod(pagedLod);
if (0 == pagedLod->getNumChildren())
{
delPageLod.push_back(pagedLod);
}
}
for (auto item : delPageLod)
{
group->removeChild(item);
}
if (0 == group->getNumChildren())
{
cout << "no data to write" << endl;
return 0;
}
if (false == osgDB::writeNodeFile(*root, outPath))
{
cout << "error "
<< "osgDB::writeNodeFile " << endl;
};
return 0;
}
通过osgDB的转换,我们成功剔除了模型的非精细部分,然后再通过之前的格式转换工具osgconv.exe转换出来的fbx模型可以成功导入虚幻引擎。上一个导入之后的示例截图:
本文主要介绍了UE5的一些重要的新特性并介绍了如何通过osgDB和osgconv.exe工具将osgb转换成fbx格式并导入到UE5。欢迎关注公众号加入技术交流群获取示例代码。