You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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密度场判断方块是否为暴露在空气中的表层方块,以此区分草方块和泥土方块:

  1. 计算当前方块的密度(Density = GetNoise(Position) - Position.Y,密度>0表示方块存在)
  2. 检查上方方块的密度,若上方无方块(密度<=0),则当前方块为地表顶层,设为草方块
  3. 若当前方块在顶层下方一定范围内,设为泥土方块

示例代码:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 08:25:34