基于FastNoiseLite的3D噪声立方世界:草方块与泥土方块区分问题
3D噪声下如何区分草方块与泥土方块的层级
我使用FastNoiseLite生成立方世界,在2D噪声模式下能正常将顶层方块设为草方块、下层方块设为泥土方块,但切换到3D噪声后,不知道该如何区分这两类层级方块。相关C++代码如下:
TArray<float> CalculateNoise(const FVector& ChunkPosition) { Densities.Reset(); // ChunkSize is 32 for (int z = 0; z < ChunkSize; z++) { for (int y = 0; y < ChunkSize; y++) { for (int x = 0; x < ChunkSize; x++) { const float Noise = GetNoise(FVector(ChunkPosition.X + x, ChunkPosition.Y + y, ChunkPosition.Z + z)); Densities.Add(Noise - ChunkPosition.Z); } } } return Densities; } void AddCubeMaterial(const FVector& ChunkPosition) { const int32 DensityIndex = GetIndex(ChunkPosition); const float Density = Densities[DensityIndex]; if (Density < 1) { // Add Grass block } // Add dirt block } float GetNoise(const FVector& Position) const // 修正原代码缺失的返回值 { const float Height = 280.f; if (bIs3dNoise) { return FastNoiseLiteObj->GetNoise(Position.X, Position.Y, Position.Z) * Height; } return FastNoiseLiteObj->GetNoise(Position.X, Position.Y) * Height; }
效果说明
- 3D噪声效果:生成的世界呈现无规律的立体起伏,无法明确区分地表顶层与下层结构
- 2D噪声效果:生成的世界有清晰的平面地表层级,能准确识别顶层草方块和下层泥土方块
解决方案
核心问题是3D噪声是全三维空间的密度场,不像2D噪声仅基于X/Z坐标生成高度值,原有的Noise - ChunkPosition.Z判断逻辑不再适用。以下两种思路可解决该问题:
思路1:2D基础高度+3D细节叠加
先用2D噪声生成地表基础高度,再用3D噪声给地表附近的方块添加细节(如洞穴、凸起),这样仍能通过Y坐标判断层级:
float GetCombinedNoise(const FVector& Position) const { const float Height = 280.f; // 2D噪声生成基础地表高度 float BaseHeight = FastNoiseLiteObj->GetNoise(Position.X, Position.Z) * Height; // 3D噪声添加细节,仅在地表15格范围内生效 float DetailNoise = FastNoiseLiteObj->GetNoise(Position.X, Position.Y, Position.Z) * 10.f; if (FMath::Abs(Position.Y - BaseHeight) < 15.f) { BaseHeight += DetailNoise; } return BaseHeight; }
修改AddCubeMaterial逻辑:
void AddCubeMaterial(const FVector& WorldPosition) { const float BaseHeight = GetCombinedNoise(FVector(WorldPosition.X, 0, WorldPosition.Z)); // 当前方块为地表顶层 if (WorldPosition.Y >= BaseHeight - 1 && WorldPosition.Y <= BaseHeight) { // 添加草方块 } // 当前方块为地表下方泥土层(可调整5为泥土层厚度) else if (WorldPosition.Y >= BaseHeight - 5 && WorldPosition.Y < BaseHeight - 1) { // 添加泥土方块 } // 深层方块(如石头) else if (WorldPosition.Y < BaseHeight - 5) { // 添加石头方块 } }
思路2:3D密度场表面检测
直接通过3D密度场判断方块是否为暴露在空气中的表层方块,以此区分草方块和泥土方块:
- 计算当前方块的密度(
Density = GetNoise(Position) - Position.Y,密度>0表示方块存在) - 检查上方方块的密度,若上方无方块(密度<=0),则当前方块为地表顶层,设为草方块
- 若当前方块在顶层下方一定范围内,设为泥土方块
示例代码:
void AddCubeMaterial(const FVector& WorldPosition) { const float CurrentDensity = GetNoise(WorldPosition) - WorldPosition.Y; const float AboveDensity = GetNoise(WorldPosition + FVector(0, 1, 0)) - (WorldPosition.Y + 1); if (CurrentDensity > 0) { // 上方无方块,为地表顶层 if (AboveDensity <= 0) { // 添加草方块 } // 顶层下方5格内为泥土层 else { const float SurfaceHeight = FastNoiseLiteObj->GetNoise(WorldPosition.X, WorldPosition.Z) * 280.f; if (WorldPosition.Y >= SurfaceHeight - 5) { // 添加泥土方块 } else { // 添加石头方块 } } } }
内容的提问来源于stack exchange,提问作者Meinhard
相关产品推荐
相关产品推荐

