地形生成Lab
柏林噪音版
想在游戏中加一个沙漠场景,所以试试生成沙漠地形。
- 生成mesh
- PerlinNoise生成山丘形状
- 砂砾闪耀(minionart有个雪地闪耀效果,可能可以用在这里
生成mesh
这一步不多说,借用catlike coding的Procedural Grid 代码,稍作修改。
PerlinNoise
修改mesh vertices的y轴坐标即可改变顶点高度。简易版使用PerlinNoise。
砂砾闪耀效果
使用一张Noise贴图——
通过控制一个灰度阈值决定像素是否显示(Cut off)。
//...
// 沙粒闪耀效果
float4 sparklesStatic = tex2D(_SparkleNoise, IN.uv_MainTex * _SparkleScale * 5);
float4 sparklesResult = tex2D(_SparkleNoise, (IN.uv_MainTex ) * _SparkleScale) * sparklesStatic;
//...
o.Albedo += step(_SparkCutoff, sparklesResult) * _SparkleColor;
o.Emission += step(_SparkCutoff, sparklesResult) * _RimColor * pow(rim, _RimPower)
HeightMap版
HeightMap和Tessellation
HeightMap的shader实现很简单,依然是vertex displacement,根据heightmap修改vert部分就可以了。
但是shader只能改变视觉效果,无法生成mesh collider(目前未找到可行方法),还得直接修改mesh的顶点坐标。通过Mesh.GetPixel获取高度图灰度值,从而决定地图高度坐标。
emmm所以最后shader还是加上了tessellation和heightmap,调节细分程度可以稍微细化一下地图,但是效果不是很好,除了视觉效果和纯shader相比不明显外,细化过度还会出现未明原因多余连线。
Triplanar Mapping
此外地形贴图还用到了Triplanar Mapping,使陡峭面的贴图按正常比例显示,不会被拉伸。
Triplanar Mapping核心代码如下:
float3 blendNormal = saturate(pow(worldNormalE * 1.4,4));
// triplanar for top texture for x, y, z sides
float3 xm = tex2D(_MainTex, IN.worldPos.zy * _Scale);
float3 zm = tex2D(_MainTex, IN.worldPos.xy * _Scale);
float3 ym = tex2D(_MainTex, IN.worldPos.zx * _Scale);
// lerped together all sides for top texture
float3 toptexture = zm;
toptexture = lerp(toptexture, xm, blendNormal.x);
toptexture = lerp(toptexture, ym, blendNormal.y);
表层贴图和侧边贴图
通过法线判断可以实现在表层覆盖其他贴图的效果,比较适用于植被、积雪等情景。
float3 worldNormalE = WorldNormalVector(IN, o.Normal);
float worldNormalDotNoise = dot(o.Normal, worldNormalE.y);
float3 topTextureResult = step(_TopSpread, worldNormalDotNoise) * toptexture;
float3 sideTextureResult = step(worldNormalDotNoise, _TopSpread) * sidetexture;
o.Albedo = topTextureResul + sideTextureResult;
用于生成山崖和简单的迷宫都很有效。
洛 美 岛 梦 幻 联 动 (危)——
TODO
【待续…】Splatmesh,covermap,virtual texture…
还有mesh要保存成文件,不然每次都重新生成一波…晚点搞…
另外mesh collider有bug,大概是tess有问题。
链接
东西放在这里惹→AlfxTerrain