Houdini

✴️Houdini丨基础复习课 - 大世界地形

by ERIN.Z, 2022-04-30


复习存货!

基础地形

BaseNode 以houdini的Heightfield系列节点为基础,创建高度场。 基础的地形空间由主要由两层noise叠加形成,第一层noise控制山势起伏,第二层noise增加细节。 noise clip节点截出水平面/底层沙砾堆积层。clip会自动生成一个我们暂时不用的mask,用maskclear清除掉。 clip erode节点使用降雨,土壤易蚀性和夹带率作为变量来模拟侵蚀和沉积物堆积,根据下方的time line来推进模拟。 颜色需要在Visualization页打开并运算一次初始Range。计算结束后勾选Freeze at Frame即可。 erode 为增加山体的结构感,将erode运算中的debris层复制至mask,对其进行slump运算。 slump 一阶段完成。 Base

河流

river 新建一个geometry node运算,使用object merge节点读入基础地形的输出节点。 绘制河流曲线,通过transform压平(像rhino里的set to Pt),然后转换为polygon。 HeightField的类型是Volume,在VolumeWrangle中定义如下区域:

int npt = nearpoint(1,@P);
vector pos = point(1,'P',npt);
float dis = distance(@P,pos);
if(dis<chf('range')){
    @mask=1;
    }

range chf()属于Houdini中的通道参数,f代表float类型。其他常用的还有: chi() chf() chu() chv() chp() ch2() ch3() ch4() chs() 点击右侧的小加号,会在下方为每一个通道创建一个滑杆,用以控制参数。 add parameter 对河床的蒙版调整后,用mask对高度进行插值,使河床中心位于相同的高度,且与周围地形有一个平滑的渐变。

@height = lerp(@height,chf('riverHeight'),@mask);

river bank 使用河床mask,用distort增加河边缓坡的细节。自此,河流部分的mesh已经处理完毕,但还是要处理一些层信息,以便后期撒点。 创建一个比河床略高的平面作为水面高度,MaskbyObject获取水面mask存为River层;River层之前的河道用layer节点做差,copylayer将mask存储为Beach层。 beach&river River

道路

road 道路与河流的做法很相似。因为有多条道路,resample后用fuse节点将靠近的点焊在一起,然后用ray节点获得曲线在地形上的投影线。 road 这里的Wrangle主要做了三件事: 1.找到用最近点生成的道路范围; 2.给范围内的点设置高度; 3.给范围内的点加mask。 与river不同的是,river的所有点可以设置至相同高度,但是道路是依附于地形的,会随山体起伏变化。所以这里用到了第三个输入端,输入上述的投影线,用于获得地表的高度。 这里一一对应的关系是由Point的编号决定的,使用point()函数用相同的编号取点即可。

int npt=nearpoint(1,@P);
vector pos=point(1,'P',npt);
float dis=distance(@P,pos);
if(dis<chf('range')&&@River<0.3)
{
    vector pos1=point(2,'P',npt);
    @height=pos1.y;
    @mask=1;
}

Road 最后将道路的mask存到Road层,道路完成。

层处理

为了导入引擎后适配Layer Materials,这里开始处理地形的材质层。 Layer 引入之前的模型,清除所有层信息(这里存储了很多Erode计算的信息),只保留地形必备的height和mask,并用copylayer创建8个空的层。 VolumeWrangle将Dirt层的初始值设为1,Noise将Grass01、02的初始值设为噪音纹理。 Maskbyfeature使用高度截取山尖,作为Snow初始值;Maskbyfeature使用坡度截取陡坡,作为Cliff初始值。 Road、River、Beach直接从输入的地形复制层即可。 为了使层和层之间不会重叠,对layer进行如下运算:

@Dirt=clamp(@Dirt-@Grass_01-@Grass_02-@Beach-@Snow-@Cliff-@Road-@River,0,1);
@Grass_01=clamp(@Grass_01-@Grass_02-@Beach-@Snow-@Cliff-@Road-@River,0,1);
@Grass_02=clamp(@Grass_02-@Beach-@Snow-@Cliff-@Road-@River,0,1);
@Beach=clamp(@Beach-@Snow-@Cliff-@Road-@River,0,1);
@Snow=clamp(@Snow-@Cliff-@Road-@River,0,1);
@Cliff=clamp(@Cliff-@Road-@River,0,1);
@Road=clamp(@Road-@River,0,1);

Layers

撒点

Foliage 需要创建的资产主要分为大面积草地、路边杂草碎石和树木。其中大面积草地在UE中通过GrassOutput制作。 路边杂草碎石分为三部分: RoadSide Foliage RoadSide Foliage Asset 为了让引擎能够识别每个点对应的使什么资产,需要为点增加一个attribute信息。导入UE时,Attribute的名称设置为unreal_instance,类型设置为String,内容为对应的instance路径。 attribute create 除了用Attribute Create节点创建属性,也可以使用Vex随机赋予不同的值:

string rock1=chs('rock1');
string rock2=chs('rock2');
string rock3=chs('rock3');
float iRand=rand(@ptnum);
if(iRand<0.5)
{
    s@unreal_instance=rock1;
}
else if(iRand<0.75)
{
    s@unreal_instance=rock2;
}
else
{
    s@unreal_instance=rock3;
}

同理对树撒点,这里不同海拔使用了不同的树种。 tree foliage 接下来就可以导出至引擎了,这一部分之前因为是Non-Commercial Edition,一直没跑通...现在用上正版软件了~下次再试试。

by ERIN.Z

2024 © typecho & elise