Houdini技术体系 基础管线(三) :UE4以选择区域的方式对地形做生成和更新 上篇

背景

前一节里,解决了Houdini地形无缝导入到UE4的流程问题。但这种方法也有它的局限性,在实际游戏项目里,LA和LD还是偏向在游戏引擎编辑器里工作,他们的一些设计也会影响到地形的信息,那么就需要Houdini对已经导入UE4中并Bake成Landscape的地形资源做二次修改。通常会选择两种方案:

  • 方案一:把整个地形和建筑都导回到Houdini里,重新过程化和调整生成后,再全部导入回UE4做处理。
  • 方案二:使用HDA节点的Input和Output,通过调用Houdini Engine API,直接在UE4里完成调用Houdini过程化节点对地形做修改。

这里方案一不但要求美术和策划对Houdini有一定了解,而且因为Houdini里和引擎的渲染效果不一致。可能还需要导入到UE4里才能看到最终效果,大地形还要做WorldCompositon和LandscapeStreamingProxy的生成。除了地形以外的的场景和建筑部分,还会和GamePlay以及优化显示逻辑相关,通常会包装成BP或Prefab的形式,这些东西要导入Houdini再导回也不仅仅是资源处理的工作。这么看方法一是非常费时费力的方法。这也导致了国内一部分项目虽然是把Houdini的地形引入到制作管线里,但也仅仅是作为WordMachined的替代品,并不能完全发挥Houdini的全部功能。

所以,我们的目标还是方案二的开发方式,除了第一次在Houdini里做完初始地形导入到UE4里生成WorldCompositon后,就不再需要重新导回到Houdini,而是在UE4里调用预先封装好过程化功能的HDA节点来完成功能。这也是近年来Ubisoft在Tom Clancy’s Ghost Recon: Wildlands和Far Cry 5里使用Houdini的方案。具体案例在GDCVault上有GDC2017和GDC2018的相关视频,这里的目标也是要UE4里用类似他们的方法来实现功能。

图:Far Cry 5的地形编辑工具示例。可以直接在编辑器里调用Houdini功能对地形做修改。

但是使用原生的UE4 Houdini Engine的前提下,无缝大地型的UE4内部修改还是会有以下几个问题:

  • 虽然Houdini Engine支持Landscape的读回到Houdini,但他Output只支持使用回读的Landacape Data信息创建一个新的Landscape:
    • 每次修改,都要重新跑一遍上节提到的生成WorldCompositon和LandscapeStreamingProxy的过程,重新对地形对切割,还是非常耽误时间
    • 虽然提供了基于Landscape Component的Input,但Output时每个Component会Cook成一个landscape,导致生成多个Component。
  • 在原生配置下,即便只处理一部分地形的迭代也必须把整个Landsacape Data通过HDA Input到Houdini来进行处理:
    • 假如使用Houdini里读入8x8k的地形,内存占用和过程化处理和交换数据量都会变大,从而导致Cook时间变长,降低迭代的速度。
    • 不能基于Componment的控制生成范围,那就需要给HDA额外加入一个选择区域的Input,导致美术工作上变的更加繁琐。
  • 很难在UE里做资源的版本管理,也不方便多人合作地形

对前面提到的一些概念和方法不了解也没关系,我接下来会用示例还原这些过程,直到最终的目标方案的原型,也就是Far Cry 5的功能效果。

图 Far Cry 5 地形编辑器,可以选择一个Terrain的Section或Sector区域来做过程化生成,极大的减小了处理和引擎与Houdini交换的资源量。

时间和篇幅的缘故,本节会分为上下篇,上半部分主要是在如何修改Houdini Engine源码,可以在UE4里基于Landscape Component进行小规模的迭代迭代的功能,下篇则是实现Houdini Engine管线的基础上,如何制作HDA节点,实现各种不同的编辑效果。

使用Houdini制作闭环

本节继续使用上一节的场景资源做作为测试用例,讲解一些HDA Input基础知识,让没有Houdini开发经验的程序人员也能很快接手Houdini Engine的改造。首先创建一个用来开发调试用的HDA节点,它的功能就是可以选中UE4场景里的一个Landscape作为Input,通过Houdini Engine把UE4 Landscape Height Data和Layer Data 转换为Heightfiled Height和Mask Data传入到HDA,在HDA里不做任何处理直接输出原始的Height和Mask,再次经过Houdini Engine生成UE4的Landscape Data。

下图就是一个Houdini闭环处理地形的流程展示,不需要打开Houdini,在UE4里就能完成闭环的操作。

如何创建一个SOP(Surface OPerators or geometry nodes )类型的Houdini Node Input的流程,Houdini Engine的官方文档里也有讲解 https://www.sidefx.com/docs/unreal/_inputs.html

方法一,Houdini里File->New Asset,按下图的创建一个新的Operator

方法二 创建一个Gemotry节点,Create Digital Asset,在HDA的Parameter里添加一个Operate Path的参数,把这个参数的与Object_Merge的Object做关联。

不论用这两种哪个方法制作都可以得到这个HDA文件,把它加入到UE资源并拖入到Level的话,按下图那样把Input类型选择为Landscape Input,就可以选择要处理LandscapeStreamingProxy。而勾选上最下面的“Export Selected Landscape Components Only”,就可以把Landscape Component作为Input输入给Houdini。但就像一开始提到的,原生Houdini Engine的这个功能并不能满足我们的需求。

基于component的更新的问题

如下图所示,原生UE4的Landscape的是支持多选Component Selection的,Houdini Engine也是支持多个Landscape Component 的Input。

选择4x4个Component作为要处理的Landscape信息,然后用Recommit看下结果.

如下图所示,虽然在效果面上,Houdini Enine把读入的LandScape Data转成HeightField Data 输入给Houdini又没有丝毫误差的的Output后转为LandScape Data,但Houdini Engine把这16个Component创建成了16个Landscape,这明显不是想要的结果。

另外要注意的是,新创建的Landscape的Transform和老的Landscape的Transform也不一样,这是Houdini和UE4的高度信息单位不同导致,这个问题也会在后面修改Houdini Engine时造成一定的困扰。而且原生的Component多选功能在Height和Mask更新上也会有一些问题。另外预先提到的一点,虽然Houdini Engine的Landscape的更新上有以上各种问题,但类似读取Landscape的信息来动态摆放,生成植物生态系统等不会修改LandscapeData的功能并不会受影响,这个具体的HDA开发也会在下篇里涉及到。

图:类似FarCry5根据选择地块的Mask信息生成植被的管线,原生的Houdini Engine也是可以胜任的。只需要一些Houdini HDA的功能开发就可以了。

定制Houdini Engine支持基于Component的生成和更新

因为时间和篇幅关系,这里提供一个不需要修改UE4源码,只少量修改Houdini Engine就可以解决问题的方法,先进入到UE4的Houdini Engine Plugin工程代码里。

和Landscape相关的功能,是在HoudiniLandscapeUtils和HoudiniEngineUtils里,建议有时间还是全看一遍,这里用注释简单描述下整个数据流程方便定位问题。

Input部分

调用FHoudiniLandscapeUtils::CreateHeightfieldFromLandscapeComponentArray函数,把选择的Landscape Component的Height Data信息转为Houdini的HeightField Data。

1. Extracting the height data

2. Convert the height uint16 data to float

3. Set the HeightfieldData in Houdini

4. Extract and convert all the layers

// 1. Extract the uint8 values from the layer

// 2. Convert unreal uint8 to float

// 3. Set the heighfield data in Houdini

Output部分:

当数据在Houdini里处理完成后,调用FHoudiniLandscapeUtils::CreateAllLandscapes基于Houdini的volume数据生成Landscape。

// First, we need to extract proper height data from FoundVolumes

// Check that all layers/mask have not changed too

// Extract the Float Data from the Heightfield

// Convert the height data from Houdini‘s heightfield to Unreal‘s Landscape

// Look for all the layers/masks corresponding to the current heightfield

// Extract and convert the Landscape layers

// Create the actual Landscape

定位到FHoudiniLandscapeUtils::CreateLandscape函数里,它的核心功能把转换后的的uint16的Landsacpe的Height信息(TArray< uint16 >& IntHeightData)和Layer信息(TArray< FLandscapeImportLayerInfo >& ImportLayerInfos),通过调用UE4的ALandscapeProxy::Import来生成一个全新的Landscape。

这里选择的解决方案是不创建新的Landscape,把HeightData和LayerData做适当的封装,直接使用FLandscapeEditDataInterface的SetHeightData和SetAlphaData输入到需要修改的Landscape的对应Component的数据做更新。

Layer Data的处理方法

为了讲解简单起见,直接在CreateAllLandscapes函数的后面加上这部分功能。其中的Height Layer的更新相对简单,把之前Import用的TArray< FLandscapeImportLayerInfo > ImportLayerInfos的数据对应的用LandscapeEdit.SetAlphaData传给老的Landscape就可以了。

// Set Layer Data
for (int32 LayerIndex = 0; LayerIndex < ImportLayerInfos.Num(); LayerIndex++)
{
    LandscapeEdit.SetAlphaData(ImportLayerInfos[LayerIndex].LayerInfo,
    SelectLandscapeComponent->GetSectionBase().X,
    SelectLandscapeComponent->GetSectionBase().Y,
    SelectLandscapeComponent->GetSectionBase().X +
    SelectLandscapeComponent->ComponentSizeQuads,
    SelectLandscapeComponent->GetSectionBase().Y +
    SelectLandscapeComponent->ComponentSizeQuads,
    (uint8*)ImportLayerInfos[LayerIndex].LayerData.GetData(), 0);
}

 

然后选中一个Component,给HDA配置上Landscape材质,以及一个HeightField  Mask Noise节点,给地形的Groud信息图层信息增加一些噪声 。

左边是处理前的效果,右边是增加噪声后的效果。

可以看到,这里已经把Houdini处理过的Height Mask信息写回到了UE4原本的Landscape Layer上,实现了目标的效果。

Height Data的处理办法

和处理Layer Data的方法类似,把Houdini Engine Output的(TArray< uint16 >& IntHeightData)用LandscapeEdit.SetHeightData函数传回给Landscape Component。

ULandscapeInfo* LandscapeInfo =
SelectLandscapeComponent->GetLandscapeProxy()->GetLandscapeInfo();
FLandscapeEditDataInterface LandscapeEdit(LandscapeInfo);

int Num = IntHeightData.Num();
for (int i = 0; i < Num; i++)
{
    // Convert Transform
    IntHeightData[i] = (IntHeightData[i] - ZeroValueInDigit)*
    SelectLandscapeScale.Z / OldLandscapeScale.Z + 32768.f;
}
// Set HeightData
LandscapeEdit.SetHeightData(SelectLandscapeComponent->GetSectionBase().X,
    SelectLandscapeComponent->GetSectionBase().Y,
    SelectLandscapeComponent->GetSectionBase().X +
    SelectLandscapeComponent->ComponentSizeQuads ,
    SelectLandscapeComponent->GetSectionBase().Y +
    SelectLandscapeComponent->ComponentSizeQuads ,
     (uint16*)IntHeightData.GetData(), 0, false );

  

Convert Transform注释部分的处理,是因为经过重新处理后Houdini的Height Field的Data Range和之前的发生了变化,导致ConvertHeightfieldDataToLandscapeData里生成的HeightData和Transform信息和Input时的Transform信息不匹配,ZeroValueInDigit和OldLandscapeScale.Z分别代表了新地形的Transform信息。需要把两个Transform信息的差异对HeigtData做修正,才能把正确的Height Data写回到Landscape。如果你发现写回的地形整体高了一块或低了一块,或者高度比例和原来不一致,那通常就是这个HeightData的还原处理出错了。所以原始的Landscape Transform也要尽量标准,例如本节示例里初始Landscape的Transform就做的尽量正规化

看下修改代码后的效果,选择一个Landscape Component地块,在HDA节点里增加一个Heightfiled Noise的节点,对Landscape Height Data做一些轻微的噪声修改:

左侧是未处理的,右侧是处理完的。可以看到地块有了噪声的高低差的效果。

继续做一个Height Field Erode的测试,用TimeShift来控制Height Field Erode的演算帧数。

下图结果是TimeShift = 30 和 TimeShift = 60的效果对比。基本上实现了用Houdini Engine对一个Landsape Component的修改功能。但是问题也很明显。处理的Component和未处理的Component的边缘高度无法很好的衔接。距离推上生产线,还有不少功能需要开发和支持。

图:Height Field Erode效果生成,相比整个Landscape的演算,一个Component只要几秒内就能完成效果计算。

总结

Houdini Engine基于Landscape Component的过程化生成,确实可以大幅度的提升生成效率和速度,但是Houdini Engine和HDA制作都还需要一系列的定制开发

  • 对多选Landscape Component的支持,并且解决多个Component之间的接缝问题。
  • Input不能只有Landscape Component来控制范围,还需要为美术提供选区的功能来控制生成范围,避免Component边界问题。

在下篇中,我们会针对这些问题,继续对Houdini Engine进行定制,以及提供针对不同功能的HDA开发的示例。

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">

原文地址:https://www.cnblogs.com/TracePlus/p/9160221.html

时间: 2024-08-01 01:03:32

Houdini技术体系 基础管线(三) :UE4以选择区域的方式对地形做生成和更新 上篇的相关文章

Houdini技术体系 基础管线(三) :UE4 Landscape Component的多选支持 下篇

背景 上篇中,我们介绍了如何修改Houdini Enigne来设置单个Landscape Compnent的Height和Layer的数据,但原生Houdini Engine并不支持多选Component的写回功能,下篇中,我们来解决这个问题. Component多选支持的修改 Houdini Engine虽然支持多个Landscape Component的选择,但是并不支持写回到Landscape Component,需要自己来实现这个功能.单个Component的实现方法上文已经接受. 多选

Houdini技术体系 基础管线(一) : Houdini与Houdini Engine的安装

Houdini 下载与安装 在官网 https://www.sidefx.com/download/ 下载最新的Production Build 版本,当前是16.5版本,需要注册帐号 PS:公司内网下载还是比较快的,如果是国内网络,下载可能会很慢和不稳定. 安装一路的默认选择就可以 后面我们需要使用的,让Houdini能够游戏引擎和DCC衔接的Houdini Engine Asset的选择安装,如果自己研究学习,又已经安装好引擎的话,可以勾选上.但正式项目会由程序员自己来维护Houdini E

Java 技术体系基础概念

Java 技术体系基础概念 =============================================================================== 概述: =============================================================================== 编程语言: [百度百科解释] 编程语言俗称"计算机语言",种类非常的多,总的来说可以分成机器语言.汇编语言.高级语言三大类.电脑每做的

java技术体系基础

编程语言分类: 1.系统级:C, C++, go, erlang 2.应用级:C#, Java, Python, Perl, Ruby, php 编程语言的类别: 指令+数据 1.面向过程:以指令为中心,围绕指令组织数据: 2.面向对象:以数据为中心,围绕数据组织指令: 虚拟机类型: 1.java虚拟机:jvm 2.Python虚拟机: pvm 开发动态网站的应用框架: 1.asp .net, jsp 思考与引申: 1.如果需要在不同的平台上都能使用开发好的java程序,需要在不同的平台上都安装

37 java技术体系基础、tomcat核心概念及使用初步、tomcat配置与应用

02 tomcat核心概念及使用初步 配置环境 node1: CentOS 6.7 192.168.1.121 CentOS 6 部署Tomcat [[email protected] ~]# rpm -ivh jdk-7u67-linux-x64.rpm  [[email protected] jdk1.7.0_67]# vim /etc/profile.d/java.sh export JAVA_HOME=/usr/java/latest export PATH=$JAVA_HOME/bin

MySQL数据库基础(三)(操作数据表中的记录)(持续更新中)

1.插入记录INSERT 命令:,expr:表达式 注意:如果给主键(自动编号的字段)赋值的话,可以赋值'NULL'或'DEFAULT',主键的值仍会遵守默认的规则:如果省略列名的话,所有的字段必须一次赋值.   INSERT SET(用的较少,一次只能插入一条记录) 命令: 插入记录INSERT SELECT 命令: 2.单表更新记录UPDATE 命令:

浏览器端技术体系概览 -- 前端开发的七种武器

科普文一则,说说我对前端技术体系(也称浏览器端技术体系)的认识,希望能让更多人了解前端,也希望能借此丰富前端开发的大局观. 去年我写了网站性能优化系列文章,看过的朋友会知道,这类文章重点并非介绍各种具体的优化技巧,而是在关注发掘这些优化点的思路和方法.然后介绍给大家多种检测手段去发现问题,进而有目标的解决问题.所有这些需要我们对有网页整个生命周期有清晰的认识,对网页中各种技术极其相互结合的方式有明确的认知.这就回归到一个更本质的问题:浏览器端技术体系是怎样的. 想用三言两语说清前端技术不大可能,

.NET平台技术体系梳理

.NET平台应用领域众多(桌面开发,web开发,移动开发),不断有新的编程爱好者开始学习或从其他平台转移到.NET开发平台..NET开发平台由微软2000年提出,到今天已经进入到了第14个年头,新技术,新框架层出不穷,目不暇接.本文第一个目的是想揭示下.NET平台一路走来的发展脉络,以飨众多刚刚进入该领域的开发者. 我们总结的泛.NET平台技术圈的知识范畴如下图所示: 二 初学者学习路径建议 由上图可见,.NET平台技术繁多,从头学起需循序渐进.结合自己的学习经验,斗胆给出一份初学者的学习建议.

[个推 CTO、前MSN中国首席架构师 谈数据智能] 之本质及技术体系要求

安森,个推CTO毕业于浙江大学,现全面负责个推技术选型.研发创新.运维管理等工作,已带领团队开发出针对移动互联网.金融风控等行业的多项前沿数据智能解决方案. 曾任MSN中国首席架构师,拥有十余年资深技术开发与项目管理经验,在大数据处理系统.大规模并发平台.分布搜索系统.手机应用开发.无线通信领域和智慧金融系统等领域拥有丰富实践经验. 引言中国移动互联网的发展见证了中国大数据行业的蓬勃发展.数据智能作为移动互联网时代的自然产物,也是未来很长一段发展阶段的核心所在.个推(每日互动)和业界的共识不谋而