/images/avatar.png

Papalqi

大世界 场景工作流

一.使用工具 1.1使用 HLOD https://www.youtube.com/watch?v=WhcxGbKWdbI 由于HLOD是减少DrawCall的方案,所以其实他会对渲染性能的提高能够起到一定的帮助作用。因为它是将场景中互相独立的静态Mesh通过顶点和材质合并的方式聚合在一起,本来由于材质和顶点Buffer的不同而没有办法形成一个统一的Drawcall,现在可以迎刃而解。很显然那些被合并的顶点和索引buffer再也不能被复用了,而且pack到一起的纹理也是一样,它们都变成了场景中独一无二的资源,所以理论上讲HLOD是一种用空间来换取时间的方法。 所以HLOD是会增加内存使用的,如果是巨量的HLOD,不仅适得其反,会影响渲染性能的使用,cook的时候一个HLOD的文件大小是及其夸张的。压缩这些HLOD文件可能花费了数个小时的时间,它大大降低了研发迭代的效率。 将世界场景设置 中的 Enable Hierarchical LODSystem打开。 我们首先在windows 界面打开HLOD管理器 我们点击 Generate Cluster, 他会把所有level里面的空间位置临近的Mesh分组为一个Cluster。如果觉得分的不好的话是可以自己手动修改的。 然后我们点击加号增加HLOD的个数,例如我们增加两个一共三个LOD 确定好之后,点击Generate Proxy Meshs 将会分组的HLOD 数据。等待一段时间。 1.1.1HLOD调试 我们选择HLOD 的视图模式 我们由近到远就可以看到HLOD的变化。 1.1.2参数设置 距离每个cluster越近,使用的LOD的越数值越小,Mesh的数据越精确。每个LOD上面都有特定的参数。 参考: https://docs.unrealengine.com/zh-CN/BuildingWorlds/HLOD/Reference/index.html 1.2使用LOD和Merge Actor 1.2.1使用LOD 所以其实我们并不需要所有的物理都变为HLOD的,当然这个部分没有踩过坑是没有办法预知的,因此我们对于某些Mesh(待定)使用LOD应该就ok。我们的每个Mesh ,都需要设置LODs。 这里我们有了标准是可以使用脚本刷的。 相关调试 1 2 r.StaticMeshLODDistanceScale r.forceLOD 由于我们的LOD是可以使用简化材质的。 1.2.2使用Merge Actor 由于HLOD的内存问题,所以另一种方案是合并actor,因为他是生成一个新的Mesh和material,所以他并不会产生额外开销。 1.3使用 Virtual Texture 首先开启 virtual texture 然后,我们将所使用的贴图进行转换 也可以在纹理编辑器里进行转换 若未使用上述转换菜单选项,将立即导致引用转换纹理的所有现有材质失效。应打开引用违规纹理的所有材质,并将纹理取样节点设为使用正确 虚拟(Virtual) 采样器类型。例如,虚拟纹理应使用 虚拟颜色(Virtual Color) 而非 颜色(Color) 采样器类别

UE4资源积累

PPT资源 https://www.slideshare.net/GerkeMaxPreussner?utm_campaign=profiletracking&utm_medium=sssite&utm_source=ssslideview https://www.slideshare.net/EpicGamesJapan https://www.slideshare.net/LearnUnreal https://www.slideshare.net/EpicGamesChina https://www.slideshare.net/unity3d 官方资源 https://ue4resources.com/ https://udn.unrealengine.com https://ue4community.wiki https://trello.com/b/TTAVI7Ny/ue4-roadmap https://unrealengine.jp 三方资源 UE4U.xyz https://www.unrealengine.com/zh-CN/resources https://romeroblueprints.blogspot.com/ https://www.tomlooman.com/ https://unreal-engine-4.zeef.com/tom.looman https://epicgames.ent.box.com/s/29ziwm7c64qqgyxbwsvgdvunow21zfkb

UE4物理动画参数

首先我们打开物理资产: 影响物理动画的是两个,一个是Profile里面物理动画的配置,还有一个是本身Body 上面的配置 一. Body的设置 Mass ,默认是根据你Body上的体积自动计算的,我们可以更改。最终影响的是惯性 LinearDamping:线性阻尼。控制Body的线性速度减缓强度。值越大,速度减小越快。 AngularDamping:角速度阻尼。控制Body的角速度减缓强度。值越大,速度减小越快。 (以上两个数值,若启用PhysicalAnimationProfile,一般不再设置这两个数值,Profile的值也影响该效果) Enable Gravity:是否启用重力。关闭后不受重力影响,只受Body的惯性影响。 CollisionReponse:是否和外部物体碰撞。需要和外部物体碰撞时打开,如在人群中穿行和碰墙壁 二. Limit的设置 原则上是根据人体骨骼活动范围设置limit,并且所有动作都应在limit中运动。为了方便,可把所有limit设为free,通过Physical Animation Profile来约束,Profile无法满足的,再去设置个别骨骼的limit,如Spine。 三. Physical Animation Profile 打开Profile 选择一个已经有的prfile,这个名字对应的配置是可以在蓝图里指定的。 选择完成后,就可以看不同的刚体对应的物理参数 Is Local Simulation:是在世界空间还是在局部空间,判断移动Kinematic时是全局还是相对父Body的。目前从代码来看我们用世界空间的比较好。 Orientation Strength:用于更正方向误差的力。值越大,越靠近动画的角度 Angular Velocity Strength:用于更正角速度误差的力。值越大,速度稳定(向动画靠近)的越快。 Position Strength:用于更正线性位置误差的力。仅可用于非局部模拟。值越大,越靠近动画的位置。 Velocaty Strength:用于更正线性速度的力。仅可用于非局部模拟。值越大,速度稳定(向动画靠近)的越快。 Max Linear Force:用于更正线性误差的最大力。(设为0) Max Angular Force:用于更正角度误差的最大力。(设为0) 四.Constraint Profile 功能:局部控制。关节驱动身体靠近动画,靠近动画的姿势,而不影响Body的属性。如果靠PhysicalAnimationProfile驱动,会导致Body过于僵硬无法移动,ConstraintProfile解决了这一个问题,但运动时需要PhysicalAnimationProfile去稳定Body的位置(全局的)。 原理:设置Constraint的Motor,setDrive驱动关联的两个Body到达动画的相对Rotation。 SkeletalMeshComponent需要设置Update Joints From Animation为true. Angular Drive Mode需要设置为Twist and Swing,Motor才会生效。 Target Orientation: 不必设置,Update Joints From Animation会取动画来设置该Orientation。

Chaos破碎性能分析

默认情况下,Chaos没有开启多线程,我们将两种方式对比.开启TaskGraph没有明显变化 一.基础测试 1.1 没有碎块 没有碎块的话,我们的性能开销是0.1ms 开启TaskGraph没有明显变化 1.2 100块碎块 当我们100块的时候,上升到了5ms 1.3 500块碎块 上升到了20ms 1.41000块碎块 上升到了60ms 测试案例,将一个box分为1000块。 二.修改参数 2.1修改Iterations 我们看到,绝大部分的物理性能的消耗不出所料是在计算物理位置的EvolutionAndKinematicUpdate上面。 集中在AdvanceOneTimeStep上面。在物理引擎中,我们的帧数其实要比物理引擎的帧数低很多,物理引擎将每帧分成更小的单位Step,每一步来判断是否发生了碰撞,如果发生了碰撞则会发生反弹等其他操作。 对于1000块,我们修改 当Iterations变为5时,48ms。为2时,28ms,为1时,25ms。 2.2增加cluster 我们Iterations的基础上,将1000块分组。增加Cluster的效果非常好,虽然我们破碎分为10个Cluster的话和没分的时候差不多。但是我们分为100个Cluster时 我们分为200个: 这里的分簇操作控制碎裂网格体的视觉质量和性能。破坏建筑物等对象时,级别1通常需要少量簇(或较大碎片),随着级别的增加会发生更多破坏(较小碎片)。 最初碎裂时无需数千碎片以进行优化,而是在建筑物倒下时落下单独碎片。 优化的另一选择是定义要碎裂的 最大簇级别(Max Cluster Level) 可以看出来,分Cluster对整个的破碎非常的有帮助。 合理的分簇能够极大的减少性能开销,我们进行多级的分组 帧数能稳定在70fps 结论 就算是调整到比较廉价的方式,其本身依旧还是开销巨大,对整个场景的破坏极具考验。

Chaos代码结构剖析

本片文章深入剖析Chaos的代码结构。 一.代码结构 Chaos的核心代码存储在Source/Runtime/Experimental中 而一些之外的代码都是以插件的形式存在于引擎之中。InteractiveToolsFramework并不属于Chaos的模块。 ChaosCore封装了一些基本的数据结构,有Array,Vector,Matrix,其考虑到了没有Unreal基本数据结构支持时应当如何处理。 Voronoi是计算几何术语,在二维空间中的一种空间划分的方案,对于离散点的空间划分中,其具有每条边到点的距离是相等的特点。 GeometryCollectionEngine,实现资源GeometryCollection的声明和应用,还有Gameplay中使用的Component和Actor实现了GeometryCollectionActor\GeometryCollectionComponent\GeometryCollectionComponent等功能。其作为UE的破碎功能和Chaos的结合实体。 FieldSys,实现控制破碎过程中使用的场的功能。如力场,sleep场,kill场等等。 ChaosVehiclesEngine,使用Chaos实现的载具功能,目前处于实验状态。 ChaosSolverEngine,每个破碎功能都必须有一个解算器,如果我们不声明的话,我们会使用默认的解算器。 Chaos,所有的物理计算,进阶和高端的操作都在这个模块当中 在引擎中,physx和chaos是无法兼容进行使用的,在编译阶段就使用宏来进行了所有的隔离操作,以保证上层的使用对底层的实现无法感知。PHYSICS_INTERFACE_PHYSX和WITH_CHAOS是完全互斥的两个宏。 当然,一些核心的调度代码存在Engine/Physics/Experimental中。 主要数据结构 我们知道,我们使用所有破碎都需要通过使用UGeometryCollectionComponent来实现,而我们的UGeometryCollectionComponent对应的破碎数据则是存储在 UGeometryCollection 中,我们在编辑器中指定和配置的都是这个数据。除了UGeometryCollection外,还有一个UGeometryCollectionCache的数据,我们可以使用UGeometryCollectionCache的数据进行与烘培减少在运行时的实时计算。 FPhysScene_Chaos,作为物理世界的物理线程与主线程的桥梁,所有与物理世界的交互都在这里进行。 TPBDRigidsSolver,真正进行物理计算的数据结构,自己玩自己的,只经过FPhysScene_Chaos进行同步交流。如果仅有一个Solver的话,我们所有的物理计算都是在一个空间中和之前是没有区别的;如果我们对场景中不同的物体指定使用不同的物理解算器,不同解算器之间是没有办法进行通信的,可能这在某些情况下会有这种特殊需求。 建立物理状态 对于破碎来讲,UGeometryCollectionComponent与一般的Component一样,也是在注册时进行物理数据的注册和提交。而其他的物理和Phx一样,上层接口上是无感知的。 从UActorComponent开始,会在注册时调用CreatePhysicsState。根据是否需要生成OverlapEvent,分为两个不同的分支。 如果不需要OverlapEvent,我们获得Wolrd 的PhysicsScene的DeferPhysicsStateCreation,延迟的创建 1 WorldPrivate->GetPhysicsScene()->DeferPhysicsStateCreation(Primitive); 对于需要的,我们将调用OnCreatePhysicsState来进行。 对于每个拥有Mesh 的Component来说,必须含有物理数据,也就是UBodySetup才能够确定其物理世界的表示方案,所以只有保证有其正确的BodySetup。 之后,会加入到PhysScene的DeferredCreate PhysicsStateComponents中。对于其后续的操作则在PhysScene阶段再进行介绍。值得说明的是,我们的初始化操作其实是针对其内部的BodySetup,我们初始化完成BodySetup后,在Scene中依旧会调用OnCreatePhysicsState来生成PhysicsState。 跟渲染一样,由于都是不同线程间进行,根据Unreal 的设计原则,不同线程之间都需要一个Proxy来进行通信和代指,从而保证线程间的安全。 对于Chaos物理系统而言,拥有自己的物理代理。 所有的物理代理都是继承于TPhysicsProxy。其类型有 FSkeletalMeshPhysicsProxy,对SkeletalMesh 的物理代理 FStaticMeshPhysicsProxy,对StaticMesh 的物理代理 TGeometryCollectionPhysicsProxy,对破碎物体的物理代理 TJointConstraintProxy,对约束节点的的物理代理 等等。 每个物体的物理状态的更新OnCreatePhysicsState的时候。在OnDestroyPhysicsState的时候销毁,这两个也分别是在组件创建和销毁的时候进行的。 当我们创建完成一个PhysicsProxy,我们将其加入到PhysicsScene中来。使用FPhysScene_Chaos::AddObject来进行,物理代理和Component的对应关系将会被记录下来。但是其物理真正加入到解算器中并一定是在这里。 在UPrimitiveComponent中首先会根据UBodySetup建立BodyInstance之后调用InitBody,将自己的物理代理加入物理世界。当然我们的破碎由于不是BodyInstance能代表的,其实我们在生成TGeometryCollectionPhysicsProxy加入Scene的时候,注册到物理世界的。 普通的BodyInstance注册到解算器 对于一般的BodyInstance,不管是StaticMesh还是SkeletalMesh,都是使用BodyInstance来表示的,所以他们都是在BodyInstance的InitBody,添加到物理世界中。 调用InitDynamicProperties_AssumesLocked。 GeometryCollection注册到解算器 对于TGeometryCollectionPhysicsProxy来说,我们需要定义三个不同的函数: 1 2 3 FInitFunc InInitFunc; FCacheSyncFunc InCacheSyncFunc, FFinalSyncFunc InFinalSyncFunc 初始化函数,这里主要是处理拥有Cache的破碎,Chaos是支持预先烘培的Cache模式,如果我们指定了Cache模式,我们将会在这里进行初始化操作.

Chaos使用文档

在这里我们将跳过如何开启、编译、下载的基本步骤。并且虽然Chaos是一整套的物理引擎,本文则不对其与Phx的通用功能做出特殊说明而只针对其本身的破碎系统 资源与编辑器 GeometryCollection 我们进行破碎的第一步就是将Mesh转化为Chaos可识别的GeometryCollection资源,GeometryCollection是Chaos的物理资源。 Mesh要求 生成GeometryCollection并不是所有的Mesh都符合要求,并且为了达到更高的效率,我们依旧需要Mesh制作中符合某些特定的标准才可以。 模型需要封闭(Watertight),无交叉(Non-Intersecting)。 对于凸物体来说其分割将会更加的灵活能施加更多的控制,所以对于复炸的模型我们需要将他的Mesh拆分开,分别配置其破碎,最后通过蓝图将这些东西聚集成整体。 我们的轴向选择需要符合Unreal的Gridding Ststem的要求,这样我们控制Width和Height的时候才能更加的高效。 要考虑的另一个概念是 材质 指定,即使模块的材质相同,也应每个材质类型应用唯一的材质ID。这样在碎裂时可生成第二个材质ID,然后即可指定适当的内部材质。 在下方视频中,几何体集由两个网格体组成,而这两个网格体共享相同纹理,但使用两个不同的材质类型。因此,石料和混凝土的内面均可使用唯一材质;如果一种材质已被使用,则可将一个材质ID指定到内面。 将多个不同的Mesh整合在一个GeometryCollection中,将会使得如果有相同材质的话会共享材质并且降低DC。 多个Mesh是可以结合成为一个GeometryCollection,虽然小的物体在空间中的拜访非常灵活,但是会造成高的DrawCall,可见的接缝,并且十字交叉的重复。大型的Mesh会导致灵活性降低,但是会隐藏接缝。 创建GeometryCollection 我们使用的所有的Chaos的破碎都需要存储在Geometry Collection的资源内。 Collision Settings, Collision Type:我们的Collision Type一共有两种,一种是Implicit-Implicit一种是Particle-Implicit。他是和Implicit Type有着密不可分的关系。使用Level Set Volumes时,应将 Collision Type设为Particle-Implicit。也可将其设为 隐式-隐式(Implicit-Implicit),但其在后台仍会检查隐式表面的碰撞粒子。 Implicit type:总共有四种,盒体、球体或胶囊体和Level Set Volumes。盒体以类似于边界框的形式包裹形体,而球体和胶囊体则放置在刚体内部来适应空间。 在模拟期间,这能加快计算速度并降低内存占用率,但会降低精度。Level Set Volumes,此类体积使用体素化网格对刚体采样,并生成几何体的有向距离场。Level Set Volumes精度更高,可调整的性能,不过内存使用更高 Min Level Set Resolution Max Level Set Resolution MinCluster Level Set Resolution MaxCluster Level Set Resolution Collision object Reduction percentage:如Box之类的碰撞,其类似于外包围盒的那种类型,一般来说包围盒都会比破碎物体本身要打,所以我们在模拟一开始包围盒之间就会交叉,调整整个参数将会降低。 破碎系统 我们将在这里来选择我们的破碎系统 碎裂方法有多种不同类型,结合不同技巧便能产生更为有趣的破坏效果。可尝试使用不同选项和设置来实现理想效果。 使用Shift-B 可以看到Bone Color,当你选择了一个GeometryCollection.