复习存货!
基础地形
以houdini的Heightfield系列节点为基础,创建高度场。
基础的地形空间由主要由两层noise叠加形成,第一层noise控制山势起伏,第二层noise增加细节。
clip节点截出水平面/底层沙砾堆积层。clip会自动生成一个我们暂时不用的mask,用maskclear清除掉。
erode节点使用降雨,土壤易蚀性和夹带率作为变量来模拟侵蚀和沉积物堆积,根据下方的time line来推进模拟。
颜色需要在Visualization页打开并运算一次初始Range。计算结束后勾选Freeze at Frame即可。
为增加山体的结构感,将erode运算中的debris层复制至mask,对其进行slump运算。
一阶段完成。
河流
新建一个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;
}
chf()属于Houdini中的通道参数,f代表float类型。其他常用的还有:
chi() chf() chu() chv() chp() ch2() ch3() ch4() chs()
点击右侧的小加号,会在下方为每一个通道创建一个滑杆,用以控制参数。
对河床的蒙版调整后,用mask对高度进行插值,使河床中心位于相同的高度,且与周围地形有一个平滑的渐变。
@height = lerp(@height,chf('riverHeight'),@mask);
使用河床mask,用distort增加河边缓坡的细节。自此,河流部分的mesh已经处理完毕,但还是要处理一些层信息,以便后期撒点。
创建一个比河床略高的平面作为水面高度,MaskbyObject获取水面mask存为River层;River层之前的河道用layer节点做差,copylayer将mask存储为Beach层。
道路
道路与河流的做法很相似。因为有多条道路,resample后用fuse节点将靠近的点焊在一起,然后用ray节点获得曲线在地形上的投影线。
这里的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;
}
层处理
为了导入引擎后适配Layer Materials,这里开始处理地形的材质层。
引入之前的模型,清除所有层信息(这里存储了很多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);
撒点
需要创建的资产主要分为大面积草地、路边杂草碎石和树木。其中大面积草地在UE中通过GrassOutput制作。
路边杂草碎石分为三部分:
为了让引擎能够识别每个点对应的使什么资产,需要为点增加一个attribute信息。导入UE时,Attribute的名称设置为
unreal_instance
,类型设置为String,内容为对应的instance路径。
除了用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;
}
同理对树撒点,这里不同海拔使用了不同的树种。
接下来就可以导出至引擎了,这一部分之前因为是Non-Commercial Edition,一直没跑通...现在用上正版软件了~下次再试试。