Electric Dreams PCG技术详解(三)——森林、岩石和场景背景

图片

森林


图片


描述

森林PCG图表主要用于创建场景中山脚下的森林。根据森林的PCG规则,系统会对地形表面进行采样,以程序化方式填充相应区域。参数化使用户配置和实时编辑更轻松。森林会被排除在PCG封闭范围区域外,并且不会与溪床以及其他手动创建的区域相重叠,方法是通过样条线定义其范围。


设置

森林程序化生成依赖以下条件:
  • 需要有一个地形
  • 公开参数(父项蓝图Actor中的变量)
  • 用于执行森林图表的PCG组件
  • 父项蓝图Actor上的PCG体积或盒体碰撞组件,用于生成内容。

森林图表位于:

  • /Game/PCG/Graphs/Forest/PCGDemo_Forest

独立的蓝图Actor(包含用于执行森林图表的PCG组件)位于:

  • /Game/PCG/Graphs/Forest/PCGDemo_ForestBP

林图表使用的所有公开参数都来自“PCGDemo_ForestBP”,这些参数可以覆盖很多节点设置,例如采样器、密度、变换、种子和范围。这些参数可以在世界中的蓝图Actor上编辑,在编辑中和在编辑器中运行时触发森林的实时更新。 

参数在蓝图中以两种不同的方式创建。全局参数是可以直接影响所有预设的变量,并直接驻留在蓝图中,而其他参数来自蓝图使用的一个预定义结构并作为预设,可以保存和循环。源结构资产位于: 

  • /Game/PCG/Graphs/Forest/PCGDemo_ForestSettings


图片
全局参数

图片

预设参数结构

Electric Dreams》环境示例项目中已经包含森林规则的关卡:

  • ElectricDreams_Env: /Game/Levels/ElectricDreams_Env
  • ElectricDreams_PCG: /Game/Levels/PCG/ElectricDreams_PCG
  • ElectricDreams_PCGForest:
    /Game/Levels/PCG/Breakdown_Levels/ElectricDreams_PCGForest


逻辑

图表概览

图片


森林图表乍看有点复杂,不过我们可以按以下顺序分析图表的各个部分,帮助我们更好地理解森林图表:岩石->主要树木、标准树木、林中空地->三级生成->大型悬崖和雾气卡片。不同颜色的注释框和大标题可以帮助你识别图表的各个部分。


地形采样和生成岩石


图片


检查森林图表时,首先要考虑岩石,因为在根据规则处理树流时会存在执行依赖。岩石分两个流,用于创建不同的资产:主要岩石Assembly和标准岩石网格体。

  • 使用两个单独的表面采样器对地形进行采样,为岩石Assembly和标准岩石网格体生成点。
    • 表面采样器的设置通过“获取Actor属性(Get Actor Property)”节点,使用父项蓝图“当前设置(CurrentSettings)”结构中设置的参数和值进行覆盖。
  • 两个流的采样点数据都使用“ForestToMountainsSwitch”子图表对法线和高度进行筛选,以防止山下的森林规则和山上的森林规则重叠。
  • 在生成森林前,通过密度和筛选操作控制总体密度和分布。
  • 使用“DiscardPointsInBumpyArea”子图表对主要岩石目标点进行Flat Area检测。将通过Flat Area检测的有效点输入“复制点(Copy Points)”,按属性输入“静态网格体生成器(Static Mesh Spawner)”节点。
  • 使用“点过滤(Point Filter)”节点将标准岩石点分成三个子流,再将它们输入加权的“静态网格体生成器(Static Mesh Spawner)”节点,分别设置相应的网格体和权重。

图片


图片



岩石的二级生成


图片


岩石的二级生成是指围绕一级岩石生成一组小型资产,包括平坦的巨石、树根、地表、小石块、树苗和蕨类植物。

  • “合并(Merge)”节点用于合并之前被分入不同数据流的所有岩石点。将合并后的点数据合集分为两个流,用于在一级标准岩石点上生成地表细节和额外的岩石。
  • 输入每个流的二级源点数据是使用“导入数据表(Import Data Table)”和“创建点网格阵列(Create Points Grid)”节点创建的,旨在实现不同的布局。然后通过“复制点(Copy Points)”节点将源点数据复制到每个目标点上。
  • 所有复制点都将通过“投影(Projection)”节点投影到地形表面上。
  • 使用“密度噪点(Density Noise)”和“密度过滤器(Density Filter)”控制点的分布,然后生成网格体。

图片


图片


通过地形采样和岩石排除生成主要树木、标准树木以及林中空地


图片


植被的生成通过三个主数据流来完成,每个数据流都以特定的表面采样器为起点。在图表的整个执行过程中,主要树木、标准树木以及林中空地三个数据流彼此紧密相关。主要树木流用于生成较大较密的树木模型。标准树木流用于在不同条件下,根据相对于林中空地和主要树木的距离来填充空间。林中空地流由非常稀疏的点组成,这些点定义了空地在整片森林中的位置。


  • 使用三个独立的表面采样器对地形进行采样,为三个流创建点:主要树木、标准树木和林中空地。
    • 表面采样器的设置通过“获取Actor属性(Get Actor Property)”和“属性过滤器(Attribute Filter)”节点,使用父项蓝图“当前设置(CurrentSettings)”结构中设置的参数和值进行覆盖。 
  • 每个流都使用“ForestToMountainsSwitch”子图表对法线和高度进行筛选,以防止山下的森林规则和山上的森林规则重叠。
  • 然后将一级岩石作为与主要和标准树木点的二进制差异,用于避免重叠。
  • 使用“距离(Distance)”节点和公开的范围参数计算标准树木点到林中空地点中心的距离。将标准化的距离写入标准树木点的密度属性。这可以让我们通过下游的选择和筛选过程调整树木的大小,在林中空地上生成特定的资产。

图片
图片
绿色的点表示主要树木点
下图为标准树木点


图片

图片
红色的点表示林中空地
下图为到林中空地的距离被写入标准树木点的密度属性


主要树木及其二级生成


图片


主要树木点不仅用于生成密集的大树,还用于生成枯树。每棵主要树木周围还会生成二级资产。


  • 主要树木点流将经历多次密度噪点、法线和筛选操作,然后生成枯树和密集的主要树木模型。
  • 大型悬崖结构和林中空地通过“差异(Difference)”节点删除主要树木点。
  • 二级资产通过两种方式创建/选择:
    • 生成根和地块的点来自“导入数据表(Import Data Table)”节点,这些点被复制到每个主要树木点上,再被投射到地形表面。
    • 小型树木和岩石来自标准树木流中经过筛选的点子集,根据它们与主要树木点的接近程度来选择。没有通过这项距离测试的点将用于在下游填充标准树木。


图片


图片


标准树木材质分布逻辑和生成

图片


将填充剩余空间的标准树木分为四个不同的区域,用于覆盖特定材质。

  • 使用“距离(Distance)”节点计算从世界原点开始的距离向量。另外,将这个距离写入点的密度(Density)属性。
  • 然后,将计算出的距离向量标准化,用于相对于阳光照射方向(在“创建属性(Create Attribute)”节点中设置)的属性向量点运算。利用该运算结果将点分为两个不同的区域:朝阳点和阴影点。
  • 将密度噪点乘以根据距离值获取的点密度。使用经过噪点处理的到世界原点的距离密度值对两块区域进行细分,最终创建出四个区域:靠近/远离太阳的朝阳点、靠近/远离太阳的阴影点。
  • 对每个经过筛选的数据流使用特定的“点配对和设置(PointMatchAndSet)”节点,确定每个区域中允许进行的加权材质覆盖。将材质软对象路径字符串写入每个点的“材质(Material)”属性。
  • 所有数据流都流入一个“静态网格体生成器(Static Mesh Spawner)”节点,并启用“按属性覆盖材质(By Attribute Material Overrides)”,将“属性[0](Index[0])”设为“材质(Material)”
图片
图片
材质覆盖的四个标准树木区域,下边为最终结果。


所有树的三级生成

图片


三级细节网格体散布在森林中的所有树木周围。这些网格体包括散落在地表上的树苗、蕨类植物、接骨木果以及枯叶。


  • 所有树流通过一个“合并(Merge)”节点合并在一起,作为“复制点(Copy Points)”节点的目标输入。
  • “复制点(Copy Points)”节点的源点数据由“导入数据表(Import Data Table)”提供。
  • 经过参数化筛选后,将三级点投射到地形表面上,再生成网格体。


图片

图片

红色的点表示三级点,下图为最终结果。



大型悬崖Assembly

图片


大型悬崖结构是导出到PCG设置资产的Assembly,仅在森林空地周围生成。利用公开的参数改变交错的空地和标准树木采样器也会影响大型悬崖的生成效果。大型悬崖结构会删除森林中的树木和岩石,并在其周围添加碎石堆。 


  • 标准树木流以及到林中空地的距离密度被作为点数据重复使用,用于生成大型悬崖。
  • 到林中空地的距离已被写入这些点数据的“密度(Density)”中,通过密度筛选在低密度范围内选择点的子集。
  • 再用“DistanceToNeighbors(到相邻点的距离)”子图表进一步筛选点,在相同的点数据上找到一组附近的点。
  • 使用蓝图中公开的覆盖参数进行变换。
  • 使用“复制点(Copy points)”节点将四个大型悬崖PCG设置资产的源点复制到它们各自的目标点数据上。通过对输入流进行密度噪点和密度筛选处理,为每个Assembly划分目标数据。


图片

图片

大型悬崖Assembly点,下边为最终结果。



山下森林中的雾气卡片

图片


在山下的森林中放置雾气卡片是为了创建深度和在山下森林的树冠中添加叠层。


  • 使用“获取地形数据(Get Landscape Data)节点”和表面采样器生成用于放置雾气卡片的点。
  • 检测是否与树流有交集,确保只在有树木的地方生成雾气卡片点。
  • 使用自定义PCG蓝图元素“LookAt(看向)”对雾气卡片点进行重定向,使其朝向世界中某个确定的位置,确保在中远距离的PCG序列视角获得最佳效果。
  • 使用自定义PCG蓝图元素“Distance To Density(距离到密度)”计算雾气卡片到中心的距离,根据该距离将森林中的雾气卡片从世界中心区域删除,防止其与河床区域重叠。剩余点输入“静态网格体生成器(Static Mesh Spawner)”节点。
图片
图片
上图为雾气卡片点,下图为最终效果。


附加信息

分区

PCG组件可以分区,以便在底层PCG分区Actor网格阵列上的实例上执行和生成失真效果,这有助于大规模世界的生成。分区功能可以在“PCGDemo_ForestBP”ActorPCG组件中启用,“ElectricDreams_Env”“ElectricDreams_PCG”也都包含这个Actor。分区可以用于将图表执行分布到更小的图块上,在实时编辑和分割生成的输出时提高性能。

设置:
  • 分区功能在PCG组件中启用或禁用(“属性们”->“高级”->“Is Partitioned(是否分区)”)。任何PCG图表都可以使用或不使用分区功能。《Electric Dreams》的森林蓝图PCG组件默认不使用分区功能,关卡中的Actor的PCG组件启用分区功能。

图片


  • 世界中的PCG世界Actor是在首次生成PCG组件时创建的。如果是2D或3D网格,并且带有“使用2D网格(Use 2DGrid)”开关,你可以在这个PCG世界Actor中设置“分区网格大小(Partition Grid Size)”。PCG世界Actor是所有PCG分区Actor的父项,PCG分区Actor是在生成分区PCG组件时自动创建的。“ElectricDreams_Env”和“ElectricDreams_PCG”关卡的分区网格大小为51200厘米。

图片

图片


  • 要想在启用分区功能时检查PCG编辑器中的节点,必须在编辑器上下文下拉菜单中选择要检查的分区Actor。属性视图只会显示所选分区Actor上下文中的数据。

图片


  • 重要提示:采样器默认与其PCG体积绑定。启用分区功能时,采样器与每个分区Actor体积绑定,这是为了防止对每个分区Actor之外的点进行采样和在每个分区Actor之外生成点,以免创建出重复重叠的点,导致内存或性能问题。如有需要,可以提供其他绑定形状,或在必须以其他方式进行采样的特殊情况下,将采样器设为无限范围。

图片



手动创建和封闭范围PCG区域的删除


Electric Dreams》环境是结合传统工作流程和程序化工作流程构建出来的。在“ElectricDreams_Env”世界的核心区域,你会发现一个手动创建的区域,我们必须把它排除在程序化规则之外,以免发生重叠或出现制作问题。 


我们采用的方法是利用样条将特定空间排除在程序化生成规则之外。我们还用程序化生成这部分区域的沟渠堤墙样条排除了PCG封闭范围区域。

图片

红色样条 = 手动创建区域,白色样条 = PCG封闭范围溪床区域



覆盖预设的蓝图结构


为了在森林和背景规则中保存和使用参数预设,我们使用了“结构(Structure)”资产,其中包含专门用于覆盖节点设置的变量。结构中的这些变量必须是术语表属性描述中列出的PCG支持的类型。


设置:
  • 创建一个结构资产,添加变量,设置面向用户的理想变量名和PCG支持的类型。

图片

  • 在我们想获取属性的Actor蓝图中设置结构。如果是森林,“PCGDemo_ForestBP”有一个“PCGDemo Forest Settings”类型的“CurrentSettings”变量,一个自定义结构。
  • 在PCG图表中使用“获取Actor属性(Get Actor Property)”节点,启用“Extract Object and Struct(提取对象和结构体)”,将“Property Name(属性名称)”设为蓝图中的结构变量名。这将创建出一个属性集,其中包含结构中的所有变量。
  • 使用“过滤属性(Filter Attribute)”节点为其相应的覆盖选择一个属性。在下图中,“获取Actor属性(Get Actor Property)”节点通过“CurrentSettings”结构创建了属性集,然后通过筛选主要树木的特定属性,覆盖“表面采样器(Surface Sampler)”的设置。

图片





背景

图片



描述

背景PCG图表主要用于生成山脉背景和世界中的远景。背景规则以程序化方式填充背景区域,根据地形创建相应背景。
它的工作原理是将预构建的岩石和树木Assembly实例化。
该图表经过参数化,用户可以轻松配置和实时编辑,它还支持基于蓝图的预设系统。


设置


背景图表依赖以下条件:

  • 地形
  • 自定义蓝图Actor,支持基于蓝图结构的预设系统,可以为图表提供参数。


背景图表位于:

  • /Game/PCG/Graphs/Forest/PCGDemo_Background


相关子图表:

  • /Game/PCG/Graphs/Forest/PCGDemo_Background_PlacementSubGraph
  • /Game/PCG/Graphs/Forest/PCGDemo_Background_VariantsSubGraph
  • /Game/PCG/Graphs/Forest/PCGDemo_Background_VariantsSubGraph_NoCulling


蓝图Actor(包含用于执行背景图表的PCG组件和预设系统)位于: 

  • /Game/PCG/Graphs/Forest/PCGDemo_BackgroundBP


相关蓝图结构:

  • /Game/PCG/Graphs/Forest/PCGDemo_BackgroundSettings


《Electric Dreams》环境示例项目中已经包含背景规则的关卡:

  • ElectricDreams_Env:/Game/Levels/ElectricDreams_Env
  • ElectricDreams_PCG:/Game/Levels/PCG/ElectricDreams_PCG

图片

背景PCG图表的输出


 

图片

图片

图片

图片

<<  滑动查看下一张图片  >>

用于填充背景的PCG设置资产

(使用预制的岩石和树木资产)



逻辑

图表概览

图片


图表通过4个相继的主要步骤生成山脉和相关树木,更远的远景通过额外的步骤生成:
1. 地形采样和应用全局参数:控制背景资产的整体规模和位置。
2. 放置:控制放置模式和用于生成资产的点的堆叠。
3. 变化:选择不同的资产,剔除某些不可见的实例。
4. 生成:生成最终的静态网格体。
5. 更远远景:参见左下角

这些步骤需要重复3次,用于创建山和树木的近景层、中景层、远景层。

图片


在上图中可以看到三个主要图层和更远的远景:
  • 绿色为近景层
  • 黄色为中景层
  • 红色为远景层
  • 紫色为更远的远景


远景层的设置

近景层、中景层和远景层的设置相同,下面我们详细看一下远景层的设置。

图片

图表远景层部分的输出

图片

灰色注释框中为远景层的创建步骤


地形采样和应用全局参数

图片


  • 使用表面采样器,根据地形生成初始点,连接Distance To Density(距离到密度)节点,计算这些点到Global_WorldOrigin向量参数(在蓝图Actor中公开)的距离。
    使用Global_WorldScale参数将这个距离重映射成0-1的范围,保存为点的密度属性。
  • 使用密度过滤器(Density Filter)节点删除密度高于Global_MaxRange参数值的点,它也来自一个蓝图Actor变量。
    由此得到的点以Global_WorldOrigin为中心形成一个圆盘,使用Global_WorldScale进行缩放,使用Global_MaxRange进行剪裁。
    使用密度噪点(DensityNoise)为密度添加噪点。

图片



点的放置(聚集和堆叠)

图片


这部分图表的功能是使用点的堆叠和聚集技术,创建逼真的岩石分布效果。

  • 从蓝图Actor的CurrentSettings_Far结构变量中提取RangeLowerBound

    和RangeUpperBound的值,覆盖密度过滤器(DensityFilter)节点的属性。


图片


  • 密度过滤器(Density Filter)将使用这些值删除点,在圆盘中创建一个洞。

图片


  • 然后使用子图表
    PCGDemo_Background_PlacementSubGraph来处理复杂的放置和堆叠工作。将整个CurrentSettings_Far属性集输入子图表,用来控制子图表的行为。

图片


  • PCGDemo_Background_PlacementSubGraph
    这个子图表的作用是创建一组经过堆叠、旋转和缩放的点,提升山脉的结构感。 

图片

PCGDemo_Background_PlacementSubGraph的布局。

图片PCGDemo_Background_PlacementSubGraph的输出。
为了获得这一效果,子图表将进行下列操作:
  • 随机选择输入点。
  • 使用DistanceToNeighbors(到相邻点的距离)PCG蓝图节点寻找点集群。这一过程的描述请参见“附加信息”。
  • 使用变换点从点集群中创建额外的点,使用随机约束垂直偏移和缩放值创建点堆栈。
  • 使用LookAt(看向)PCG蓝图节点重定向所有点(聚集堆叠的点和单独的点),让它们朝向中点(Global_WorldOrigin / 参考点)
  • 应用另一层随机约束垂直偏移和缩放值。
  • 一部分点围绕Z轴旋转90度,另一部分点围绕Z轴旋转180度,围绕中心形成十字图案。
  • 根据点到中心的距离增加点的缩放值和高度。

大部分操作由属性集(AttributeSet)中的参数控制,这些参数是通过子图表的设置输入提供的。 

属性集源自主图表:CurrentSettings_Far,来自Actor蓝图结构变量。

图片