• ue4烘焙失败

    2016-11-29 10:46:03
    ue4中经常会遇到烘焙失败的问题,有的显而易见,有的则不那么容易被发现。这里记录一下工作中遇到的烘焙失败问题,希望在以后遇到类似的问题能作为参考。 首先看下ue4官方文档对烘焙的解释 内容烘焙 虚幻引擎将...

    ue4中经常会遇到烘焙失败的问题,有的显而易见,有的则不那么容易被发现。这里记录一下工作中遇到的烘焙失败问题,希望在以后遇到类似的问题能作为参考。

    首先看下ue4官方文档对烘焙的解释

    内容烘焙

    虚幻引擎将内容资源存储为在其内部应用的特殊格式,比如贴图数据存储为PNG格式, 或者音频存储为WAV格式。但是,针对不同平台,这些内容需要转换成各种格式, 这是因为该平台使用专有的格式,不支持虚幻引擎使用的存储资源的格式, 或者是因为存在一种更加节约内存或提高性能的格式。将内容从内部格式转换为针对特定平台的格式 的过程,称为烘焙 。 

    一般解决烘焙问题的思路如下,先确定是哪个地图烘焙失败,在DefaultEditor.ini中包含所有地图列表,可以通过增删地图列表来逐步定位出问题的地图。然后列表中可以只放出问题的地图,这样可以加快烘焙速度,也可以缩小可能导致烘焙失败的范围。

    最后要解决烘焙失败原因,就是通过分析烘焙log,以下是一次烘焙失败ue4 editor Output Log窗口输出的日志(由于日志较长,这里只截取了部分输出)

    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:473][  0]LogLinker:Warning: Can't find file '/Game/GunWorks/GW_Guns/AAR/upper_receivers/upper_receiver_01/AAR_Upper_Receiver'
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:473][  0]LogUObjectGlobals:Warning: Failed to load '/Game/GunWorks/GW_Guns/AAR/upper_receivers/upper_receiver_01/AAR_Upper_Receiver': Can't find file '/Game/GunWorks/GW_Guns/AAR/upper_receivers/upper_receiver_01/AAR_Upper_Receiver'
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:474][  0]LogLinker:Warning: Can't find file '/Game/GunWorks/GW_Guns/AAR/upper_receivers/upper_receiver_01/AAR_Upper_Receiver'
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:474][  0]LogUObjectGlobals:Warning: Failed to load '/Game/GunWorks/GW_Guns/AAR/upper_receivers/upper_receiver_01/AAR_Upper_Receiver': Can't find file '/Game/GunWorks/GW_Guns/AAR/upper_receivers/upper_receiver_01/AAR_Upper_Receiver'
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:474][  0]LogUObjectGlobals:Warning: Failed to find object 'Object /Game/GunWorks/GW_Guns/AAR/upper_receivers/upper_receiver_01/AAR_Upper_Receiver.AAR_Upper_Receiver'
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:475][  0]LogRedirectors:Warning: String Asset Reference '/Game/GunWorks/GW_Guns/AAR/upper_receivers/upper_receiver_01/AAR_Upper_Receiver.AAR_Upper_Receiver' was not found! (Referencer '/Game/GunWorks/Materials/GW/GunWorks_M.GunWorks_M:PreviewMesh')
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:476][  0]LogLinker:Warning: Can't find file '/Game/Environment/Meshes/TEMP_01'
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:476][  0]LogUObjectGlobals:Warning: Failed to load '/Game/Environment/Meshes/TEMP_01': Can't find file '/Game/Environment/Meshes/TEMP_01'
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:476][  0]LogLinker:Warning: Can't find file '/Game/Environment/Meshes/TEMP_01'
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:476][  0]LogUObjectGlobals:Warning: Failed to load '/Game/Environment/Meshes/TEMP_01': Can't find file '/Game/Environment/Meshes/TEMP_01'
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:477][  0]LogUObjectGlobals:Warning: Failed to find object 'Object /Game/Environment/Meshes/TEMP_01.TEMP_01'
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:477][  0]LogRedirectors:Warning: String Asset Reference '/Game/Environment/Meshes/TEMP_01.TEMP_01' was not found! (Referencer '/Game/SideScrollerKit/Materials/M_Glass_wall_beam.M_Glass_wall_beam:PreviewMesh')
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:785][  0]LogShaders:Warning:     CompilingMasterWeaponShader: Platform=PCD3D_SM4, Usage=LightingModel=MSM_DefaultLit, BlendMode=BLEND_Opaque, SpecialEngine=0, TwoSided=0, TSNormal=1, InjectEmissiveIntoLPV=0, Masked=0, Distorted=0, BlockGI=0, Usage={bUsedWithSkeletalMesh,bUsedWithVxgiVo
    xelization}
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:841][  0]LogShaders:Warning:         116 Shaders among 3 VertexFactories
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:917][  0]LogShaders:Warning:     CompilingMasterWeaponShader: Platform=PCD3D_SM4, Usage=LightingModel=MSM_DefaultLit, BlendMode=BLEND_Opaque, SpecialEngine=0, TwoSided=0, TSNormal=1, InjectEmissiveIntoLPV=0, Masked=0, Distorted=0, BlockGI=0, Usage={bUsedWithSkeletalMesh,bUsedWithVxgiVo
    xelization}, StaticSwitch'Debug AO'=False, StaticSwitch'White Paint Pattern'=False, StaticSwitch'Two Color Pattern'=False, StaticSwitch'Light Metal Pattern'=False, StaticSwitch'Plasma on Channel Two'=False, StaticSwitch'Plasma on Channel One'=False, StaticSwitch'Plasma on Channel Three'=False, StaticSwitch'Panini Projection'=True, StaticMask'Plasma Channel O
    ne'=R, StaticMask'Plasma Channel Two'=G, StaticMask'Plasma Channel Three'=G
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.48.59:975][  0]LogShaders:Warning:         116 Shaders among 3 VertexFactories
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.49.00:000][  0]LogShaders:Warning:     CompilingM_ShockProto_Screen: Platform=PCD3D_SM4, Usage=LightingModel=MSM_Unlit, BlendMode=BLEND_Additive, SpecialEngine=0, TwoSided=0, TSNormal=1, InjectEmissiveIntoLPV=0, Masked=0, Distorted=0, BlockGI=0, Usage={bUsedWithSkeletalMesh,bUsedWithStaticLi
    ghting,bUsedWithVxgiVoxelization}, StaticSwitch'Panini Projection'=True
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.49.00:043][  0]LogShaders:Warning:         72 Shaders among 3 VertexFactories
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.49.00:061][  0]LogShaders:Warning:     CompilingM_Shock_Flair_Multi_Color_2: Platform=PCD3D_SM4, Usage=LightingModel=MSM_Unlit, BlendMode=BLEND_Additive, SpecialEngine=0, TwoSided=1, TSNormal=1, InjectEmissiveIntoLPV=0, Masked=0, Distorted=0, BlockGI=0, Usage={bUsedWithSkeletalMesh,bUsedWith
    ParticleSprites,bUsedWithBeamTrails,bUsedWithStaticLighting,bUsedWithVxgiVoxelization}, StaticSwitch'Panini Projection'=True
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.49.54:427][  0]LogOutputDevice:Error: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: begin: stack for UAT
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: [2016.11.29-01.49.54:429][  0]LogWindows:Error: === Critical error: ===
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: Fatal error!
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x00000000
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-Engine.dll!UMaterialInstance::HasOverridenBaseProperties() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\engine\private\materials\materialinstance.cpp:2848]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-Engine.dll!UMaterialInstance::InitStaticPermutation() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\engine\private\materials\materialinstance.cpp:1489]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-Engine.dll!UMaterialInstance::PostLoad() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\engine\private\materials\materialinstance.cpp:2084]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-CoreUObject.dll!UObject::ConditionalPostLoad() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\coreuobject\private\uobject\obj.cpp:748]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-CoreUObject.dll!EndLoad() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\coreuobject\private\uobject\uobjectglobals.cpp:1452]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-CoreUObject.dll!LoadPackageInternal() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\coreuobject\private\uobject\uobjectglobals.cpp:1171]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-CoreUObject.dll!LoadPackageInternal() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\coreuobject\private\uobject\uobjectglobals.cpp:1286]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-CoreUObject.dll!ResolveName() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\coreuobject\private\uobject\uobjectglobals.cpp:696]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-CoreUObject.dll!StaticLoadObjectInternal() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\coreuobject\private\uobject\uobjectglobals.cpp:783]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-CoreUObject.dll!StaticLoadObject() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\coreuobject\private\uobject\uobjectglobals.cpp:853]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-CoreUObject.dll!FRedirectCollector::ResolveStringAssetReference() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\coreuobject\private\misc\redirectcollector.cpp:118]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-UnrealEd.dll!UCookOnTheFlyServer::TickCookOnTheSide() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\editor\unrealed\private\cookontheflyserver.cpp:1650]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-UnrealEd.dll!UCookCommandlet::NewCook() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\editor\unrealed\private\commandlets\cookcommandlet.cpp:1375]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-UnrealEd.dll!UCookCommandlet::Main() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\editor\unrealed\private\commandlets\cookcommandlet.cpp:679]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-Cmd.exe!FEngineLoop::PreInit() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\launch\private\launchengineloop.cpp:1780]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-Cmd.exe!GuardedMain() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\launch\private\launch.cpp:114]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-Cmd.exe!GuardedMainWrapper() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\launch\private\windows\launchwindows.cpp:126]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-Cmd.exe!WinMain() [e:\work\viba\unrealengine-vxgi-4.12\engine\source\runtime\launch\private\windows\launchwindows.cpp:200]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: UE4Editor-Cmd.exe!__scrt_common_main_seh() [f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:255]
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: kernel32.dll
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: ntdll.dll
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: ntdll.dll
    MainFrameActions: Cooking (Windows): UE4Editor-Cmd: 

    这里优先查看error,根据红色标出的部分,很快就知道是由于空指针导致的烘焙失败,再往下有具体烘焙失败的调用堆栈(有时候没有堆栈输出,可以尝试直接从代码启动editor,然后烘焙)

    通过堆栈分析,发下以下代码是导致最终烘焙失败的原因:


    2848行,空指针,很明显,Parent是空指针导致的,也就是说,是由于MaterialInstance的Parent是NULL导致的烘焙失败

    然后我们从后往前排查输出日志(主要是看有error、warning和fail的),发现材质文件MasterWeaponShader一打开,editor直接闪退,很明显是这个文件导致的烘焙失败,然后查找引用这个文件的地方,发现这些文件项目中并没有用到,于是删除相关文件,再次烘焙,就成功了。

    ps:好的习惯是重视烘焙和打包中的warning,尽可能消除这些warning,这样不仅能提高烘焙和打包速度,还能尽快的定位问题。

    还有一种比较笨但比较实用的方式是从地图中不断删除物体后进行烘焙,这样可以不断缩小范围(因为只有被地图引用到的资源才会被烘焙)


    展开全文
  • 症状为:虽然swarm连接到了100%,然而之后就卡住一动不动,一看看log是连接tcp什么agent什么失败的。 虽然把所有物体都设置成非静态可以不构建光照也不会有红字。。但还是不甘心 于是赶紧去官网社区学习一个: ...

    不知从哪天开始,我的ue4.13就突然无法成功构建光照了,

    症状为:虽然swarm连接到了100%,然而之后就卡住一动不动,一看看log是连接tcp什么agent什么失败的。

    虽然把所有物体都设置成非静态可以不构建光照也不会有红字。。但还是不甘心

    于是赶紧去官网社区学习一个:

    先是第一个映入眼帘的方案1——改swarm的配置:

    主要就是把enablestandalonemode这一项从false改成了true,

    然并卵

    再次构建仍是同样的结局。。

     

    于是我继续寻找解决方案,冒出了方案2,有个说什么和windows安全策略有关,原文如下:

    By googling it, I found this web page http://www.sitefinity.com/developer-network/knowledge-base/details/this-implementation-is-not-part-of-the-windows-platform-fips-validated-cryptographic-algorithms-exception , that explained to Go to Start > Control Panel > Administrative tools > Local Security Policy. The Group Policy dialog appears. Under the "Local Policies" heading, select "Security Options" and look for the entry, "System cryptography: Use FIPS compliant algorithms for encryption, hashing, and signing." If this entry is enabled, disable it. Open the registry editor and browse the following path. Make sure this registry subkey is set to 1: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\fipsalgorithmpolicy

    Which I've done and straight after this it worked again! Hope it can help people who have been stuck with this thing!

    Thanks

    Geoff
    然而,我在win10根本找不到传说中的Local Security Policy。。。知道怎么打开这个设置的的可以一试
     
    接下来是方案3,意思也差不多,要允许防火墙通过,我干脆把防火墙关了,也毫无卵用。。。。。。
     
    于是我就继续依靠设为可移动物体勉强维持,
    直到有一天!
    我突然觉得自己的物品栏好low,虽然尝试过不同的背景图总免不了山寨气息,经过对比我正在玩的绝地求生大逃杀,幡然醒悟——物品栏ui什么的可以很简洁,但前提是背景要虚化。
    于是我赶紧进入控件蓝图寻找传说中的blur,竟然搜出来一片空白!原来这竟然是4.15版本的新特性!
    下载新版本虽麻烦,但看着眼前的ui心有不甘,再加上要与时俱进的理念,我果断打开epic launcher添加了新版本!
    果然发现多了一项的功能,
    于是画面就能成功变模糊了
     
    之后,我又突发奇想:“会不会因为版本换了就能成功构建光照了呢?”
    我点下了仅构建光照,几乎做好了任务管理器立即结束的准备了。
    然而,swarm连接到100%以后,双击点开swarm,那个进度条居然在动!!
    数秒之后,光照构建完成了!!!
    实在是很棒棒哦
     
    最终总结
    所以如果你遇到和我一样的问题,最靠谱的解决方法就是更新引擎版本啦,如果已经是最新版,那就试试删了重装吧。。

     

    转载于:https://www.cnblogs.com/wzj998/p/6745184.html

    展开全文
  • 这个ue4烘焙失败(仅构建灯光:Build Lighting Only),我也上网查了很多解决方案:包括 重新编译UnrealLightmass.cpp、设置Swarm等等。 最终解决方案: 第一步:打开ue4c++项目或打开UE4.sln先将vs中Dubug Editor...

    这个ue4烘焙失败(仅构建灯光:Build Lighting Only),我也上网查了很多解决方案:包括 重新编译UnrealLightmass.cpp、设置Swarm等等。

    最终解决方案:

    第一步:打开ue4c++项目或打开UE4.sln先将vs中Dubug Editor模式改为Development Editor

    第二步:在vs中找到UnrealLightmass.cpp重新编译

    第三部:将vs中Development Editor改回Dubug Editor,启动重新Build Lighting Only即可

    问题估计出在ue4本身,缺少lib库

    展开全文
  • 当使用者在UE4的编辑器内点下了Build按钮,一系列Build命令被触发,而“光照”则是其中重要的一环。我希望粗略的了解一下这其中背后的流程,随后我发现这个过程和 Swarm、Lightmass 这两个概念有关。具体来讲,这个...

    本篇目标

    当使用者在UE4的编辑器内点下了Build按钮,一系列Build命令被触发,而“光照”则是其中重要的一环。我希望粗略的了解一下这背后的代码逻辑,随后我发现这个过程和 SwarmLightmass 这两个概念有关。具体来讲,这个过程涉及的代码分布在下面几个部分中:

    1. UnrealEd模块中相关的代码。主要是EditorBuildUtils.h/cppLightmass文件夹中的代码、StaticLightingSystem文件夹中的代码。
    2. SwarmInterface模块。定义了与Swarm进行交互的接口。
    3. \Source\Programs\UnrealLightmass项目。负责生成 \Engine\Binaries\Win64\UnrealLightmass.exe
    4. \Source\Programs\UnrealSwarm文件夹包含的几个c#项目。负责生成\Engine\Binaries\DotNET\SwarmAgent.exe\Engine\Binaries\DotNET\SwarmCoordinator.exe。以及依赖的一些dll。

    我的目标是弄明白在一次Lightmass的Build流程中,这几个部分所扮演的角色。
    关于Lightmass这套系统的一些原理,我从《Lightmass源码分析之 与Swarm交互 - 知乎》中以及前后相关的文章中学到了很多。

    观察依赖关系

    SwarmAgent.exe和SwarmCoordinator.exe

    这几个部分中,Swarm的程序是相对独立的。在《官方文档:Unreal Swarm》中也可以看到,当在另一台机器上部署swarm来帮助联机渲染时,只需要将Swarm相关的exe与dll拷贝过去就可以了,并不需要UE4引擎本身。

    \Source\Programs\UnrealSwarm下,主要有两个sln:SwarmAgent.slnSwarmCoordinator.sln
    打开SwarmCoordinator.sln后可以发现一个同样叫SwarmCoordinator的项目,而这个项目的属性应用程序输出类型Windows应用程序,也就是会输出exe。而剩余的项目的输出类型都是类库,也就是会输出dll。此外,可以看到SwarmCoordinator项目依赖了SwarmCommonUtils项目SwarmCoordinatorInterface项目
    在这里插入图片描述
    同理,打开SwarmAgent.sln可以发现:Agent项目依赖了AgentInterface项目SwarmCommonUtils项目SwarmCoordinatorInterface项目UnrealControls项目
    在这里插入图片描述
    也就是说,AgentCoordinator 都依赖了SwarmCommonUtils以及各自的Interface。不过 Agent 还额外依赖了UnrealControls,以及Coordinator的Interface。看来Agent调用了Coordinator的接口。
    总结这几个程序集的依赖关系:
    在这里插入图片描述

    UnrealLightmass.exe

    UnrealLightmass是一个C++项目,所以用了UBT进行编译,因此也有配套的UnrealLightmass.Target.cs这个目标描述文件,以及UnrealLightmass.Build.cs这个模块描述文件。
    UnrealLightmass这个项目的属性页可以看到它调用了UBT并使用UnrealLightmass.Target.cs作为目标,最后输出UnrealLightmass.exe。
    在这里插入图片描述
    UnrealLightmass.Build.cs可以看到它依赖了一些诸如CoreCoreUObject这些UE4核心的模块,以及SwarmInterface模块。

    SwarmInterface模块

    SwarmInterface.Build.cs中可以看到它只依赖了CoreCoreUObject模块。但它还指出了需要AgentInterface.dll

    // Copy the AgentInterface DLL to the same output directory as the editor DLL.
    RuntimeDependencies.Add("$(BinaryOutputDir)/AgentInterface.dll", "$(EngineDir)/Binaries/DotNET/AgentInterface.dll", StagedFileType.NonUFS);
    
    // Also copy the PDB, if it exists
    if(File.Exists(Path.Combine(EngineDirectory, "Binaries", "DotNET", "AgentInterface.pdb")))
    {
    	RuntimeDependencies.Add("$(BinaryOutputDir)/AgentInterface.pdb", "$(EngineDir)/Binaries/DotNET/AgentInterface.pdb", StagedFileType.DebugNonUFS);
    }
    

    此外,关于这个模块我目前不太理解的是,它还包括一些C#代码:
    在这里插入图片描述
    那么这些C#代码该如何与其他C++部分交互呢?有待后续研究。
    不过在其中的SwarmInterface.cs中确实能看到它需要AgentInterface

    UnrealEd模块

    UnrealEd模块包含了相当多的内容,烘焙光照只是其中一部分。
    UnrealEd.Build.cs中可以看到,它依赖了SwarmInterface模块。
    而对于UnrealLightmass,它需要include:

    // Add include directory for Lightmass
    PublicIncludePaths.Add("Programs/UnrealLightmass/Public");
    

    搜索Lightmass命名空间也确实发现了很多使用之处:
    在这里插入图片描述

    总结依赖关系图

    他们之间的依赖关系可以表示成如下:
    在这里插入图片描述
    箭头的含义并不尽相同,为此我标注了每一个箭头。但相同的是:箭头尖端的代码对箭头尾端的代码是无知的。

    观察StaticLightingSystem的各个阶段

    当按下Build按钮后:
    在这里插入图片描述
    FEditorBuildUtils::EditorBuild被调用
    在这里插入图片描述
    随后,UEditorEngine::BuildLighting被调用来构建光照,而FStaticLightingSystem负责来维护整个光照构建流程。
    FStaticLightingSystem有私有变量CurrentBuildStage表示了当前所处的阶段:

    /** Lighting comes in various stages (amortized, async, etc.), we track them here. */
    enum LightingStage
    {
    	NotRunning,
    	Startup,
    	AmortizedExport,
    	SwarmKickoff,
    	AsynchronousBuilding,
    	AutoApplyingImport,
    	WaitingForImport,
    	ImportRequested,
    	Import,
    	Finished
    };
    FStaticLightingSystem::LightingStage CurrentBuildStage;
    

    下面,尝试粗略观察一下每个阶段所做的事情。

    0. NotRunning

    CurrentBuildStage在构造函数中赋值为NotRunning
    随后,当构建光照一开始就被赋值为Startup
    在这里插入图片描述

    1. Startup

    这个阶段包含了很多准备工作,主要是在FStaticLightingSystem::BeginLightmassProcess中完成的。

    1.1 GatherStaticLightingInfo

    在这里插入图片描述
    上面的信息就是来自于:
    在这里插入图片描述

    1.2 CreateLightmassProcessor

    BeginLightmassProcess中创建了一个新的FLightmassProcessor对象。

    而在FLightmassProcessor的构造函数中,FSwarmInterface接口的OpenConnection函数被调用。

    FSwarmInterfaceImplFSwarmInterface的实现。而FSwarmInterfaceImpl::OpenConnection具体执行的内容实际由C#代码所指定。具体来说:
    C++有一个FSwarmInterface:
    在这里插入图片描述
    而C#也有一个FSwarmInterface
    在这里插入图片描述
    不过C++的版本的OpenConnection等函数并没有本体,只是企图从外部得到一个函数指针。而C#版的就有具体函数的行为。
    在C#版的FSwarmInterfaceOpenConnection函数中,EnsureAgentIsRunning被调用,而它启动了SwarmAgent.exe
    在这里插入图片描述

    1.3 InitiateLightmassProcessor

    其中FLightmassExporter::WriteToChannel尝试将“光照”、“模型”、“地形”等数据从UE的格式导出为Lightmass的格式:
    在这里插入图片描述
    例如灯光:

    void Copy( const ULightComponentBase* In, Lightmass::FLightData& Out )
    {	
    	FMemory::Memzero(Out);
    
    	Out.LightFlags = 0;
    	if (In->CastShadows)
    	{
    		Out.LightFlags |= Lightmass::GI_LIGHT_CASTSHADOWS;
    	}
    
    	if (In->HasStaticLighting())
    	{
    		Out.LightFlags |= Lightmass::GI_LIGHT_HASSTATICSHADOWING;
    		Out.LightFlags |= Lightmass::GI_LIGHT_HASSTATICLIGHTING;
    	}
    	else if (In->HasStaticShadowing())
    	{
    		Out.LightFlags |= Lightmass::GI_LIGHT_STORE_SEPARATE_SHADOW_FACTOR;
    		Out.LightFlags |= Lightmass::GI_LIGHT_HASSTATICSHADOWING;
    	}
    
    	if (In->CastStaticShadows)
    	{
    		Out.LightFlags |= Lightmass::GI_LIGHT_CASTSTATICSHADOWS;
    	}
    
    	Out.Color = In->LightColor;
    
    	// Set brightness here for light types that only derive from ULightComponentBase and not from ULightComponent
    	Out.Brightness = In->Intensity;
    	Out.Guid = In->LightGuid;
    	Out.IndirectLightingScale = In->IndirectLightingIntensity;
    }
    

    从中就可以看出来它得到一个U对象ULightComponentBase的参数,并将他们赋值给了一个F对象FLightData对应的参数。而FLightData是在\Source\Programs\UnrealLightmass\Public\SceneExport.h中所定义的。
    InitiateLightmassProcessor最后,CurrentBuildStage被赋值为AmortizedExport
    在这里插入图片描述
    随后,FEditorBuildUtils::EditorBuild返回。

    2. AmortizedExport

    之后,FStaticLightingSystem::UpdateLightingBuild()在主循环中被调用,不断处理接下来的阶段:
    在这里插入图片描述
    LightmassProcessor->ExecuteAmortizedMaterialExport()返回“完成时”,CurrentBuildStage被赋值为SwarmKickoff

    3. SwarmKickoff

    CurrentBuildStage==SwarmKickoff时,KickoffSwarm()立马被调用,其中的逻辑很简单:

    bool bSuccessful = LightmassProcessor->BeginRun();
    if (bSuccessful)
    	CurrentBuildStage = FStaticLightingSystem::AsynchronousBuilding;
    

    LightmassProcessor::BeginRun中,UnrealLightmass.exe以及其依赖的dll被指定:
    在这里插入图片描述
    这些信息被加入到了一个NSwarm::FJobSpecification对象中,而它将作为调用FSwarmInterface::BeginJobSpecification时的参数。

    最后,当LightmassProcessor->BeginRun()成功时,CurrentBuildStage被赋值为AsynchronousBuilding

    4. AsynchronousBuilding

    此时,UE4编辑器内会不断更新目前的进度:
    在这里插入图片描述
    此处的代码是:

    FText Text = FText::Format(LOCTEXT("LightBuildProgressMessage", "Building lighting{0}:  {1}%"), FText::FromString(ScenarioString), FText::AsNumber(LightmassProcessor->GetAsyncPercentDone()));
    FStaticLightingManager::Get()->SetNotificationText( Text );
    

    最后,当LightmassProcessor->Update()给出“完成”的结果时,CurrentBuildStage会被赋值为AutoApplyingImport(如果失败的话则直接被赋值为Finished)
    在这里插入图片描述

    5. AutoApplyingImport

    接下来:
    在这里插入图片描述
    FStaticLightingManager::ProcessLightingData()中,FStaticLightingSystem::FinishLightmassProcess()被调用,它将CurrentBuildStage赋值为了Import
    在这里插入图片描述
    当然,这只是暂时的,因为在FStaticLightingManager::ProcessLightingData()执行后CurrentBuildStage就变为了Finished了。

    6. Finished

    CurrentBuildStage变为了Finished之后,ActiveStaticLightingSystem将变为NULL,因此,FStaticLightingSystem::UpdateLightingBuild()再也不会被执行了:
    在这里插入图片描述
    至此Build流程结束。

    总结

    总的来说,目前的观察还是在一个粗粒度级别上的。对于很多细节还并不明白,例如:

    • SwarmInterface模块中的C#代码如何与C++部分进行交互?
    • SwarmAgentSwarmCoordinator将如何交互?
    • FLightmassExporter::WriteToChannel中的数据将怎样导出给Lightmass?
    • Lightmass的结果又将如何返回?

    这些都值得后续研究。

    展开全文
  • 对玩家而言,UE4带来的作品都是不折不扣的视觉...而虚幻4引擎(以下简称UE4)就是其中之一,在这款引擎中已经诞生了诸如《铁拳7》《地狱之刃》《帕拉贡》等一系列大作。对玩家而言,这些作品都是不折不扣的视觉盛...

    转载:http://wemedia.ifeng.com/7884171/wemedia.shtml

    对玩家而言,UE4带来的作品都是不折不扣的视觉盛宴。

    在手游品质越发上扬的如今,已经有不少厂商开始使用一些性能更好的引擎,去尝试游戏制作了。而虚幻4引擎(以下简称UE4)就是其中之一,在这款引擎中已经诞生了诸如《铁拳7》《地狱之刃》《帕拉贡》等一系列大作。对玩家而言,这些作品都是不折不扣的视觉盛宴。

    日本网站4Gamer曾刊登一篇文章,分享了使用UE4在图像渲染中会遇到的难点以及解决方法,分享人是该引擎的开发商Epic Games日本分公司的高级工程师篠山範明。

    在研讨会上,篠山首先展示了虚幻4的整体流程图,随后他对和流程图上各功能板块有关的技术进行了介绍。

    绘制物体缓冲的“Base Pass”时要注意的问题

    我们先来把整个流程分为不同的单元,在各个单元里进行深入解读。

    首先从上图左起第二个板块“Base Pass”开始。Base Pass等同于产生了物体缓冲(G-Buffer)。

    众所周知,UE4的绘制引擎采用了延迟渲染(Deferred Rendering)。所谓延迟渲染,是指将一个场景的几何体(3D模型、多边形)的光照、阴影、质感搁置到一旁,先着手于绘画,然后在后半段再对光照、阴影、质感进行处理的处理方式。

    即给人一种把原本的多边形先绘制出来的印象,实际上不仅要绘制多边形,前者的参数还需要配合后面光照和阴影的处理。其输出目标,在成为复数缓冲时具有普遍性,但是这里的缓冲我们称之为“物理缓冲”。

    为何要做这么麻烦的事情?其实延迟渲染有两个优点。第一个优点就是能将十分复杂的光照、阴影以每次一像素的方式进行处理。第二个优点是并不明确限定用于光照的动态光源数,所以可以进行丰富的光照渲染。

    现代游戏图像在绘制复杂的场景时需要大多的光源,而在移动复杂着色器的时候,最终其结果不是在画面上输出,而是通过像素着色器,处理像素的编写和撤销,导致耗时严重、性能下降。为了全力回避这一点而开发出的就是延迟渲染。

    物体缓冲是指使用后照明和后处理特效的中间过渡环节

    根据以上提到的这些,使用Base Pass输出物体缓冲需要注意的两点。

    第一点简而言之即“不绘制没进入视线的对象”。

    这种“投影剔除”(Frustum Culling),一般是通过CPU端来处理;为了整体覆盖被称为“包围球”(Bounding sphere)的各个3D对象,对象是否在视野内的判定标准,是通过预先设定的包围球来实行的。

    举一个包围球被错误(或是正确)设定的案子。这种情况下如果绘制没有被正确地剔除,会导致最终明明没有绘制,但作为GPU的绘制对象却投入了渲染管道(rendering pipeline),造成GPU产生多余的负担。

    什么程度的剔除会成功,可以通过Stat初始视图(Stat InitViews)指令的“视锥体裁剪基元(Frustum Culled Primitives)”进行确认。

    另外,实行强制冻结渲染(FreezeRendering)指令后移动镜头,就能够确认视野外绘制了什么。如果那个时点上,视野外本应剔除的3D对象被描绘了出来,就会显示出不能被剔除的理由。在这种情况下需要特别注意确认包围球的设置。

    强制冻结渲染能够看到此时点摄像机提出的结果

    Base Pass要注意的第二点,是“不计算多余的像素”。

    在图像处理的流程中,使用像素着色器实际处理前,会有运行深度测试(Z 测试)的“Pre Z 测试”这一步骤。从这里着手处理的像素,会因为被某个东西所遮挡而无法绘制出来,这时可以进行撤销处理。

    但是,像半透明对象这种会伴随α测试的绘制、视差遮蔽映射这种像素着色器处理后会重新编写深度值的情况,就不进行Pre Z测试,而通过处理实行分路迂回。

    运行α测试的隐藏(Masked)材料

    像素深度撤销(Pixel Depth Offset)可以变更像素深度(Pixel Depth)

    但是,就算是不透明的对象,设定回避Pre Z测试之后,便无法撤销本来能够撤销的Pre Z 测试。这种情况是因为虽然用了像素着色器处理,但是(之后的)Z测试失败,这一操作被撤销了,虽然绘制结果没有变得奇怪,不过性能会跌落到最坏结果。

    Z值的预阶段“Z预阶段”的注意点

    下一个主题是“Z预阶段(Z Pre Pass) ”。UE4的渲染管道,是在Bass Pass的物体缓冲写出来之前,在仅预处理深度值(Z值)之后,运行Z预阶段。

    事先预处理深度值的目的,是将最终影像和同一深度缓冲的内容结果,在透视前获得。Z预阶段之后的Base Pass则是,参考预先得出的深度值缓冲进行Z预测试,因此通过在最终的画面里不留下像素痕迹(即编写后又被消去的像素),以回避像素着色器的运行。

    虚幻4只将背景对象这种静态对象计入Z预阶段,而动态对象则不计入Z预阶段,以上设定为默认设定。但是虚幻4可以按照客户要求来设定项目文件“早Z阶段(Early Z-pass)”和“动态早Z阶段(Movables in early Z-pass)”。

    或者通过勾选“作为遮光板使用(Use as Occluder)”可以设定各对象单位是否计入到Z预阶段之中。

    各项目的关闭渲染选项里面,有“作为遮光板使用”这一项目。在设定为默认为ON时,勾选为off,就能够调整各项目单位是否参与早Z

    通常默认设定应该就可以了,但是在多边形数很多的场景中,Z预阶段的运行本身会对GPU造成很大负担,所以这种场景下,上面提到的两个设定,通过选择on/off来比较性能可能会比较好。

    光照的前段处理“预照明”需要注意的点

    虚幻4中通过血溅和弹痕这种投射材质贴图来实行的印花式绘制,是在光照(Lighting)之前,即通过“预照明(Pre-Lighting)”部分来处理并设计的。对于后段的光照处理,可以将印花式绘制囊括在光照对象里。

    和印花绘制相同,“从所有方向插入有关假想环境光的遮蔽率”(Ambient Occlusion,环境光遮蔽)的处理,也能通过预照明来完成。

    与这种预光照绘制相关的麻烦已经成了常见问题,比如“印花被描绘得照明颜色过深”、“设置天窗后,印花下面变透明了”等等。

    从结论来说,这是“虚幻4的做法”,当然《虚幻4》也提供了回避此类问题的对策。那就是“延迟贴花(DBuffer Decals)”功能。

    所谓延迟贴花(或称Deferred Decal),是指和将印花进行物体缓冲不同,而是使用被称作“延迟贴花”这一印花专用特殊缓冲来进行绘制,用物体缓冲进行光照和阴影处理之后,延迟贴花的内容也反映并实行了出来。印花的绘画结果统合到了物体缓冲之中后,也因此出现了上文提到的问题。为了回避这个问题,要准备专用的缓冲。

    但是,加上利用物体缓冲这一条件,绘制比之前的处理线程更多,绘制负担变高也成为其瓶颈。

    虽然导致负担变高了,但是应该实行印花表现而导入物体缓冲吗?还是说应该选择别的表现方式来回避延迟贴花,这需要开发者好好考虑后再做决定。

    通过光源周围的处理而改变性能的“照明”阶段

    接下来,篠山说明的是光照的阶段。虚幻4的光照分为“静态光照(Static)”、“固定光源(Stationary)”、“动态光照(Movable)”三种光照范畴。

    最先提到的静态光照,为通过全部事先计算过的光线映射来处理的静态光照。这一事先计算,可以使用专用的光照烘培,来计算将间接光都考虑在内的光照。

    其次是固定光源,固定光源的光照本身是以实际时间来运行的,但是只有阴影计算是事先进行了处理的。

    具体而言,固定光源在UE4的图像引擎内部会被当作一般的动态光源,但配置到场景里又成了基本不动的光源。因为它不动,所以也可以在阴影贴图中用于预先生成阴影。

    虽然有点复杂,但这种做法有个好处,就是配置的固定光源一组最多可以放置4个,其内部处理是稍有限制。

    固定光源预生成的阴影贴图中,一个光源能够分别对应αRGB中4条通道的像素格式。也就是说,第一个光源对应α通道,第二个光源对应R通道,以此类推。所以在αRGB中最多对应四个光源,一组光源的上限也就是四个。

    如果设置第五个固定光源,那么它将被当作动态光源来处理,即便是定义为固定光源,也不会提升其性能。

    固定光源在一张阴影贴图上最多设置4个,超过第五个将被视作动态光源

    而动态光源如前文所述,包括阴影生成在内,它将完全在运行时进行处理。

    我们之前说过延迟渲染下动态光源的数量不受限制,再来看它实际的性能。

    设置两组对比场景,一是将100个照射范围狭小的动态光源放置到同一场景内,二是将8个照射范围较大的光源放置到同一场景内,对比两者的负荷大小。

    得出的结果是后者的负荷更高。这里的负载大也可以看作是计算量大。而计算量的大小,取决于场景内各个像素受到多少个光源的照射。所以比起处理八个像素各自被一个光源照射,处理一个像素被八个光源照射的负荷要更高。

    负荷率大小:蓝>绿>红

    UE4可以通过光效复杂性(Light Complexity)功能来查看光源的处理负荷,所以在设计的时候,可以不依赖延迟渲染的特性,而通过精确计算光源负荷来构建场景。

    通过光效复杂性功能,就可以查看已设置的光源的负荷率

    光照反射存在最优解吗?

    不仅限于UE4,在所有即时游戏的美术中,需要不少设计技巧的就是光照反射(Reflection)。

    如果反射的材料是镜面反射更强的金属类,那么周围的场景就应该被映入其中,如果以材料的角度来看,就相当于受到了周围所有光源的照射。光照反射要应对的就是周围所有的光源,所以它是在表现材料材质的时候,关于真实程度的关键要素。

    在UE4当中,有三种反射生成方法来处理会引起镜像、映照等情况的材料,如下图所示。

    第一种是采用反射探头来生成静态反射。

    在场景的任意位置都可以预先设置坐标,然后可以进行全方位的透视,最后会生成立方环境贴图(CubeMap)材质。而这里的预生成坐标点,被称作反射探头(Reflection Probe)。

    静态反射就好比是反射探头处拍下的360°照片

    关键的问题在于:在反射探头处获得的全方位场景,应该影响到场景内多大的范围。

    依然采用对比分析,首先在一个场景里配置一个静态反射,将其设置为影响整个场景;再配置200个静态反射,设定为只能影响非常狭小的范围,可以看到两者的绘制负荷差距不大。

    但是在设置了200个静态反射的例子中,如果将各自的影响范围调大,符合就会急速增大。

    其原因与动态光源的例子相同。如果将多个静态光源的影响范围扩大,那么在绘制一个像素的时候,就必须参考计算多个静态光源的参数,负荷自然就增大了。

    稍微调大200个静态反射的影响范围,负荷就立刻增大

    其实,已经配置了相邻的反射探头时,再将两者的影响范围重叠的意义并不大。反射探头的设置以及其影响范围的设定如果不合情合理,那么就会增加很多无效的计算负荷。

    如下图实例的配置就更为合理:

    红圈:让整个场景都处于光照反射的影响范围内。

    覆盖各个房间的蓝圈:主要的静态反射,在这里可以定义大致的统筹性参数。

    绘制物件细节的绿圈:仅配置在能产生光照反射的特殊物件上。

    第二种是屏幕空间反射(Screen Space Reflection,简称SSR)。

    屏幕空间反射会根据透视图的结果,在画面坐标系中进行局部的光线跟踪,在运行时刻(Runtime)上实时生成计算结果。

    这种处理方式的好处是,即便仅截取场景中任意一瞬间的画面,也会精确地反映出动态角色以及动态光源影响下的光照反射。相对的缺点,就是对于画面外场景的影响,会被完全无视掉。

    使用SSR最典型的报错,就是暴露了这个缺点所造成的。弥补它的有效方法,就是结合静态反射来做处理。

    如右图,岩壁左侧被画面隔断的地方,应该在水面中被反射,但是因为岩壁被隔断在画面之外,所以无法被正确反射

    第三种是平面反射(Planar Reflection)。

    这是将场景准确的映入平面的光照反射处理手段。如下图实例,以水平面为反射面,从视点E来看右侧的岸边,那么相当于在水下的视点E'来透视上下颠倒的岸边的场景。所以被反射的场景需要进行两次绘制,光照反射处理的负荷必然会高出不少。

    又因为处理负荷比较高,所以平面反射常限定在水面等平面上使用,同时画面的品质非常高。由于这些特性,比较推荐在过场动画中使用平面反射的处理。比如《地狱之刃》在GDC 2016上放出的宣传片,其中就使用了平面反射的处理技术。

    关于半透明的各种问题

    不仅限于UE4,半透明物件的绘制在实时图形绘制领域都算是很难处理的问题。UE4在绘制半透明物件时也会遇到不少棘手的问题。

    离我们最近的问题,可以说就是粒子效果,可能是因为日本的画师都特别喜欢粒子效果,所以对它比较关心吧。

    UE4在绘制半透明粒子效果时,不会更新深度值(Depth)。

    将特效配置在场景中

    但深度值没有变化

    这种情况下会产生的问题就是,将深度值设为关键值时,后期处理会变得很奇怪。

    如下图所示,聚焦到中间的火焰时,利用景深来让图像增加朦胧感,但火焰的粒子效果在地平线上方的都被模糊了,下方则没有变模糊,这样的图像就非常奇怪。

    这就是因为火焰的粒子效果没有深度值,所以Z缓存(Z buffer)里只存在地面的制图深度值。再加上地平线上的背景里镜头非常的遥远,所以背景和火焰都被判断为离镜头非常遥远,就被做了模糊处理。模糊处理器是无法判断有没有火焰粒子效果的,于是就成了这副样子。

    为了解决这类问题,就要使用到独立透明度(Separate Translucency)功能。

    使用时,半透明粒子效果在绘制时仍然不会更新深度值,但它被分离到别的缓存中,与景深等后期处理分开。

    换句话说,就是将半透明物件与不透明物件的绘制分开,在后期处理时优先应用于不透明物件。

    在通常的后期处理中,粒子效果的绘制与普通场景的绘制是在同一缓存里处理的

    而利用独立透明度功能,就可以将粒子特效分离到另一个缓存里,并将其与后期处理分隔开

    对比两种处理效果的区别

    利用这个功能的确能够避免半透明粒子效果出现一些奇怪的模糊情况,但是却没法给它添加适当的模糊处理。所以即便能够避免问题,但解决不了实际的困难。

    所以即便是UE4,也会存在很多限制,而引擎的开发方还在试图解决这些问题。

    而在半透明绘制方面,还存在一个很棘手的问题,也就是绘制的负荷过高。首先可以思考一个问题:让画面整体的颜色都改变的后期处理,与近让画面一部分出现冒烟的粒子效果,哪边的处理负荷更高?

    简单的看,可能因为画面整体的像素数很多,所以可能是前者更高,但其实答案恰恰相反。

    乍一看,半透明粒子效果的烟雾仅占画面的一小部分,实际上它是经过多次重叠绘制而成的。查看粒子的驱动线的框架,原因就一目了然了。在画面的同一部分,烟雾的粒子改变大小并反复绘制了多次。

    我们可以用着色复杂性(Shader Complexity)功能的排错视图,来查看。

    在这个视图中,重复绘制的区域会用红色表示,可以借此判断产生问题的部分。越红则表示改区域中,粒子绘制的负荷越高,需要调整。

    降低粒子绘制负荷最有效且最简单的手段,就是用独立透明度功能,将粒子绘制分离到别的缓存重,用低分辨率进行绘制。

    可以将反复绘制、重合的半透明粒子用低分辨率绘制,再调整好合适的大小,与主透视图合成就可以了。如果将绘制半透明粒子的缓存降低为纵横各半的分辨率,那么简单算下来绘制负荷就能变为原先的1/4,要是再将其减半,就能变为1/16。

    在低分辨率的缓存里绘制,然后扩大并合成,就意味着粒子的轮廓会变得更加模糊,而原本就是半透明的粒子即便更模糊一些,产生的影响也不会有多少。但分辨率调得过低,也会暴露出分辨率不高的问题,所以选择缓存分辨率的时候要相当慎重,与负荷变化放在一起寻找最佳的配置。

    以上三张图就是在半透明物件的缓冲分辨率在100%、50%、10%的绘制状态下,绘制负荷的变化

    粒子绘制的符合降低方法还有一种,就是在粒子动画中,完全透明区域更多的时候可以用到的粒子剪影(Particle CutOut)功能。

    通常的粒子是由两个多边形构成的,而粒子剪影的原理,就是为了避开完全透明的区域,由多个多边形自动分割来进行绘制。

    虽然这样一来多边形的数量会增加,但由于能够避免像素着色器的无意义运行,所以在大量的粒子进行绘制时,这或许会减轻负荷。

    粒子剪影会自动分割多边形

    利用着色复杂性功能的排错试图,可以看到左侧的四边形粒子,与右侧的多边形粒子,在绘制时产生的重复绘制区域更少

    UE4中顺序被固定的后期处理

    后期处理就好比相片修饰一样,需要对最后的绘制结果进行加工处理。

    相片修饰通常是针对2D的照片,在3D游戏内的图像方面,由于需要利用透视图中附带的多种信息,对图像进行三维的加工,所以两者差距非常大。

    不进行后期处理(左)与进行后期处理(右)的区别

    UE4中预设了诸如色调、景深、光晕等加工图像的多种表现形式。

    而UE4比较有特色的是,能够将后期处理的效果,设置到3D场景内的指定位置,或者是特定的摄像头上,所以能够实现诸如“进入3D场景某个位置的时候就会有景深的表现”,或是“在这个摄像头上绘制图像的时候需要棕色调”等效果处理。

    所以在用UE4的后期处理时,建议最好熟记处理的顺序,因为处理顺序无法改变,只能按部就班地进行。

    结语

    尽管文章到此结束了,但其实还有很多内容没有提到(几百页ppt),仅从提到的内容来看,也能发现,对于想要用UE4做好游戏的开发者来说,花时间打磨游戏的细节是必不可少的,而这份指南能切实的解决很多使用上的问题。

    感兴趣的读者可以访问下面的链接(PS:需要翻墙)。

    http://www.slideshare.net/EpicGamesJapan/cedec2016-unreal-engine-4

    展开全文
  • 三年前开始接触ogre引擎,由于工作需要一直进行图形方面的研发和尝试,随着引擎技术的进步,ogre的与Cryengine3、Unreal3等一线图形引擎在画面上的差距越来越大,主要原因在于ogre目前的设计趋于一套开放性的架构,...
  • 网站导出20190118

    2019-01-18 11:07:02
    Bookmarks   书签栏   重要网站   资源商店 Artlist.io - Music Licensing For Video, Film & YouTube ...unity3d插件免费下载 商业资源代购 团购 unity外包 Unity时空 ...unity3...
  • Unity3D 脚本参考

    2012-01-19 14:55:54
    Unity3D 脚本中文参考 (1) 这是一个关于Unity内部脚本如何工作的简单概览。 Unity内部的脚本,是通过附加自定义脚本对象到游戏物体组成。在脚本对象内部不同的函数被特定的事件调用。最常用的列在下面: ...
1
收藏数 8
精华内容 3