前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Unreal随笔系列4:UE4关闭指定平台距离场烘培

Unreal随笔系列4:UE4关闭指定平台距离场烘培

作者头像
JohnYao
发布2023-03-23 10:31:41
4940
发布2023-03-23 10:31:41
举报
文章被收录于专栏:JohnYao的技术分享

引言

我们项目构建了Linux版本的客户端,用于DS的压测。最近一段时间, Unreal Linux Client的构建时间异常的久,所以简单的探究了下Cook的原理。最终通过关闭linux平台下的距离场(Distance Field)烘培,缓解了构建时间的问题。

一 烘培,渲染背景知识

介绍具体问题前,先了解下背景知识。

Cook 烘培

Unreal在构建的过程中,大致执行如下四步。

烘培(Cook)的过程,是将Editor内Assets转变为运行在各平台的Assets。这个过程一般会执行三个流程:

  1. 剔除Assets中Editor相关内容
  2. 生成指定平台需要的内容(主要是渲染向)
  3. 转变成指定平台专用文件

Render 渲染

渲染(Render)和烘培(Cook)是相对平行的两个概念。 渲染主要和如下概念有关

代码语言:javascript
复制
render  渲染
static mesh  网格体
material 材质
shader  着色器
texture 贴图

简单的说,render是在mesh(网格体)上进行着色的过程,这个过程最终是由material(材质)完成。material又由shader代码(着色器)和texture(贴图)构成。

Unreal内的类间关系大致如下:

Cook和Render的关系可以简单的描述为,Cook阶段会为Render生成很多必要内容。本文标题中的距离场就是其中之一。

二 Distance Field 距离场的烘培问题

有向距离场(Signed Distance Field) (SDF),会将各点距离最近表面的距离保存到体积纹理中。网格体外的每个点保存的距离为正值,网格体内的每个点保存的距离为负值。

它有两个具体的应用:

  1. DistanceFieldShadows (DFS),距离场柔和阴影。
  2. DistanceFieldAO (Distance Field Ambient Occlusion),距离场环境光遮蔽。

引言中提到的烘培问题就出现在为DistanceFieldAO生成相关数据的过程。通过gdb得到了Cook阶段,引擎的执行堆栈:

代码语言:javascript
复制
UStaticMesh::Serialize
    FStaticMeshRenderData::Serialize
        FDistanceFieldAsyncQueue::BlockUntilBuildComplete

上述堆栈的上下文代码如下:

代码语言:javascript
复制
uint8 ClassDataStripFlags = 0;

#if WITH_EDITOR
        const bool bWantToStripDistanceFieldData = Ar.IsCooking() 
            && (!Ar.CookingTarget()->SupportsFeature(ETargetPlatformFeatures::DistanceFieldAO) || !Ar.CookingTarget()->UsesDistanceFields());

        ClassDataStripFlags |= (bWantToStripDistanceFieldData ? DistanceFieldDataStripFlag : 0);
#endif

        FStripDataFlags StripFlags(Ar, ClassDataStripFlags);
        if (!StripFlags.IsDataStrippedForServer() && !StripFlags.IsClassDataStripped(DistanceFieldDataStripFlag))
        {
            if (Ar.IsSaving())
            {
                GDistanceFieldAsyncQueue->BlockUntilBuildComplete(Owner, false);
            }

            for (int32 ResourceIndex = 0; ResourceIndex < LODResources.Num(); ResourceIndex++)
            {
                FStaticMeshLODResources& LOD = LODResources[ResourceIndex];

                bool bValid = (LOD.DistanceFieldData != nullptr);

                Ar << bValid;

                if (bValid)
                {
#if WITH_EDITOR
                    if (Ar.IsCooking() && Ar.IsSaving())
                    {
                        check(LOD.DistanceFieldData != nullptr);

                        float Divider = Ar.CookingTarget()->GetDownSampleMeshDistanceFieldDivider();

                        if (Divider > 1)
                        {
                            //@todo - strip mips
                            LOD.DistanceFieldData->Serialize(Ar, Owner);
                        }

可以看到这里的逻辑,就是等待距离场的异步构建完成,然后将构建得到的内容序列化到各层级的LOD中。

我简单魔改验证了下,在构建linux client时,忽略如上烘培逻辑确实大大减少了构建时间。 而且和相关同学确认,该部分逻辑不影响Gameplay。

不过比较正式的方法应该是修改Cooking Target的Support Feature,初略看了下,大致在如下类进行修改:TLinuxTargetPlatform, FLinuxPlatformProperties。

三 关于烘培的后续TODO项

手头还有其他事情要处理,有一些关于烘培的细节,后续抽时间再研究下:

  1. 现在Linux Client时间比DS构建仍然长很多,说明还有很多和渲染相关的逻辑在烘培阶段进行, 但单纯的魔改IsDataStrippedForServer会有报错。后续继续研究下,缩短Cook时间的可行方法。
  2. 烘培的更多细节,包括editor资源的哪些部分会转成uexp,shader的单文件存储方式等。
  3. 烘培逻辑的全流程梳理,包括CookOnTheFlyServer,Package Save等逻辑。

随笔系列说明

23年新挖一个《Unreal随笔系列》的坑。所谓随笔就是研究过程中的一些想法随时记录;细节可能来不及考证,甚至一些想法可能也不太成熟,有失偏颇;希望读者也可以帮忙指正和讨论。这个系列主要求量,希望每个月给自己布置一些研究小课题,争取今年发满12篇。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 一 烘培,渲染背景知识
    • Cook 烘培
      • Render 渲染
      • 二 Distance Field 距离场的烘培问题
      • 三 关于烘培的后续TODO项
      • 随笔系列说明
      相关产品与服务
      文件存储
      文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档