Voxel Burst Noise Sampler
Critical Instructions
- •100% Burst Compatible: KHÔNG dùng
UnityEngine.Mathf.PerlinNoise— nó không Burst-safe. DùngUnity.Mathematics.noise. - •Deterministic: Cùng seed + coordinate → cùng kết quả. Không dùng
Randomkhông seed. - •Job Ready: Mọi hàm noise phải gọi được trong
IJobParallelFor.Execute()mà không vi phạm safety. - •Project Convention: Đặt file vào
Assets/Scripts/Core/Jobs/hoặcAssets/Scripts/Environment/.
Core Principles
- •Unity.Mathematics: Dùng
noise.cnoise()(classic Perlin),noise.snoise()(simplex),noise.cellular()cho noise cơ bản. - •FBM Layering: Xếp chồng nhiều octave noise để tạo chi tiết tự nhiên.
- •3D Noise: Thế giới voxel yêu cầu 3D noise (không chỉ 2D heightmap) cho cave, overhang.
- •Scale & Offset: Luôn parameterize frequency, amplitude, persistence, lacunarity, seed offset.
Noise Types Reference
1. Perlin Noise (Classic)
Smooth, gradient-based. Dùng cho terrain hills, gentle elevation.
csharp
using Unity.Burst;
using Unity.Mathematics;
/// <summary>
/// Burst-safe Perlin noise wrapper.
/// </summary>
[BurstCompile]
public static class BurstNoise
{
/// <summary>
/// 2D Perlin noise, range approximately [-1, 1].
/// </summary>
[BurstCompile]
public static float Perlin2D(float2 coord, float frequency, float2 offset)
{
return noise.cnoise((coord + offset) * frequency);
}
/// <summary>
/// 3D Perlin noise cho cave/overhang generation.
/// </summary>
[BurstCompile]
public static float Perlin3D(float3 coord, float frequency, float3 offset)
{
return noise.cnoise((coord + offset) * frequency);
}
}
2. Simplex Noise
Ít artifact hơn Perlin ở chiều cao. Tốt cho organic features.
csharp
/// <summary>
/// 3D Simplex noise, range approximately [-1, 1].
/// </summary>
[BurstCompile]
public static float Simplex3D(float3 coord, float frequency, float3 offset)
{
return noise.snoise((coord + offset) * frequency);
}
3. Cellular / Worley Noise
Tạo pattern dạng tế bào. Dùng cho ore veins, crystal formations, biome boundaries.
csharp
/// <summary>
/// Cellular noise. Returns (F1, F2) distances.
/// F1 = khoảng cách tới điểm gần nhất. F2 - F1 = cell edge.
/// </summary>
[BurstCompile]
public static float2 Cellular2D(float2 coord, float frequency, float2 offset)
{
return noise.cellular((coord + offset) * frequency).xy;
}
4. Fractal Brownian Motion (FBM)
Xếp chồng nhiều octave noise → chi tiết đa tỷ lệ.
csharp
/// <summary>
/// FBM: Xếp chồng octaves với persistence giảm dần.
/// Tạo terrain tự nhiên có cả đồi lớn lẫn chi tiết nhỏ.
/// </summary>
[BurstCompile]
public static float FBM3D(float3 coord, FBMParams param)
{
float value = 0f;
float amplitude = 1f;
float frequency = param.BaseFrequency;
float maxValue = 0f;
for (int i = 0; i < param.Octaves; i++)
{
value += noise.cnoise((coord + param.Offset) * frequency) * amplitude;
maxValue += amplitude;
amplitude *= param.Persistence; // typically 0.5
frequency *= param.Lacunarity; // typically 2.0
}
return value / maxValue; // Normalize to [-1, 1]
}
/// <summary>
/// Parameters cho FBM noise generation. Burst-safe struct.
/// </summary>
public struct FBMParams
{
public float BaseFrequency; // 0.01 - 0.1 cho terrain
public float Persistence; // 0.4 - 0.6 (amplitude decay per octave)
public float Lacunarity; // 1.8 - 2.2 (frequency multiply per octave)
public int Octaves; // 4 - 8
public float3 Offset; // Seed-based offset
public static FBMParams Default => new FBMParams
{
BaseFrequency = 0.02f,
Persistence = 0.5f,
Lacunarity = 2.0f,
Octaves = 6,
Offset = float3.zero
};
}
Project-Specific Patterns (VisualWorld)
Terrain Density Function
csharp
/// <summary>
/// Hàm mật độ 3D: density > 0 = solid, density <= 0 = air.
/// Kết hợp heightmap (2D FBM) + cave carving (3D noise).
/// </summary>
[BurstCompile]
public struct TerrainDensityJob : IJobParallelFor
{
[WriteOnly] public NativeArray<VoxelData> Voxels;
public int3 ChunkSize; // (32, 32, 32)
public int3 ChunkWorldOffset; // Chunk position in world coords
public float VoxelSize; // 0.02m (2cm)
// Noise params
public FBMParams TerrainFBM; // Macro terrain shape
public FBMParams CaveFBM; // Cave carving
public FBMParams OreFBM; // Ore distribution
public float SeaLevel; // Y level for water
public float CaveThreshold; // Density cutoff for caves
public void Execute(int index)
{
// Flat index → 3D local coord
int lx = index % ChunkSize.x;
int ly = (index / ChunkSize.x) % ChunkSize.y;
int lz = index / (ChunkSize.x * ChunkSize.y);
// World position
float3 worldPos = (new int3(lx, ly, lz) + ChunkWorldOffset) * VoxelSize;
// --- 1. Base terrain height (2D FBM) ---
float terrainHeight = BurstNoise.FBM3D(
new float3(worldPos.x, 0, worldPos.z),
TerrainFBM
) * 64f + 32f; // Map to world height
// --- 2. Density = height - y ---
float density = terrainHeight - worldPos.y;
// --- 3. Cave carving (3D noise) ---
float caveNoise = BurstNoise.FBM3D(worldPos, CaveFBM);
if (caveNoise > CaveThreshold)
density = -1f; // Carve cave
// --- 4. Determine material ---
var voxel = new VoxelData();
if (density > 0)
{
voxel.State = 1; // Solid
voxel.MaterialID = DetermineMaterial(worldPos, density);
}
else if (worldPos.y < SeaLevel)
{
voxel.State = 2; // Liquid (water)
voxel.MaterialID = 10; // Water ID
}
else
{
voxel.State = 0; // Air
}
Voxels[index] = voxel;
}
private byte DetermineMaterial(float3 pos, float density)
{
// Surface layer (density < 2) → Grass/Dirt
if (density < 2f) return 1; // Grass
if (density < 5f) return 2; // Dirt
// Ore distribution (cellular noise)
float oreNoise = BurstNoise.FBM3D(pos, OreFBM);
if (oreNoise > 0.7f) return 20; // Iron Ore
if (oreNoise > 0.85f) return 21; // Gold Ore
return 3; // Stone (default deep material)
}
}
Biome Blending
csharp
/// <summary>
/// Xác định biome tại vị trí (x,z) bằng Cellular noise.
/// Trả về biome weights cho blending giữa các biome lân cận.
/// </summary>
[BurstCompile]
public static int GetBiome(float2 worldXZ, float frequency, float2 offset)
{
float2 cell = BurstNoise.Cellular2D(worldXZ, frequency, offset);
float biomeValue = cell.x * 4f; // Map F1 tới biome index
return (int)math.clamp(biomeValue, 0, 3);
// 0=Plains, 1=Forest, 2=Desert, 3=Mountains
}
Common Presets
| Use Case | Noise Type | Frequency | Octaves | Persistence |
|---|---|---|---|---|
| Macro terrain | FBM (Perlin) | 0.005 - 0.02 | 6-8 | 0.5 |
| Hills/valleys | FBM (Perlin) | 0.02 - 0.05 | 4-6 | 0.45 |
| Cave tunnels | FBM 3D (Simplex) | 0.03 - 0.08 | 3-4 | 0.5 |
| Ore veins | Cellular + Perlin | 0.1 - 0.3 | 2-3 | 0.6 |
| Surface detail | FBM (Perlin) | 0.1 - 0.5 | 2-3 | 0.3 |
| Biome zones | Cellular 2D | 0.001 - 0.005 | 1 | — |
| Rivers | Ridged FBM | 0.005 - 0.01 | 4 | 0.5 |
Seed Management
csharp
/// <summary>
/// Tạo deterministic offset từ world seed.
/// Mỗi noise layer có offset riêng để tránh correlation.
/// </summary>
[BurstCompile]
public static float3 SeedToOffset(uint worldSeed, int layerIndex)
{
// Hash-based: mỗi layer có hash riêng từ seed
uint h = math.hash(new uint2(worldSeed, (uint)layerIndex));
return new float3(
(h & 0xFFFF) / 65535f * 10000f,
((h >> 8) & 0xFFFF) / 65535f * 10000f,
((h >> 16) & 0xFFFF) / 65535f * 10000f
);
}
Validation Checklist
- • Không dùng
UnityEngine.Mathf.PerlinNoisehayUnityEngine.Random - • Tất cả hàm noise biên dịch được với Burst
- • FBM normalize output về range [-1, 1] hoặc [0, 1] tùy use case
- • Seed deterministic: cùng input → cùng output
- • Frequency phù hợp voxel size (2cm) — không quá cao gây aliasing
- • Không allocate trong Execute (mọi buffer được allocate trước)
- • Terrain density function tạo kết quả hợp lý (có đất, có trời, có cave)