Terrain feel: biome regions ~10x larger (Voronoi cell size 96->960); terrain height now eases across biome borders via a Voronoi distance blend (smooth, and ~25x cheaper than the old 169-sample box blur); mountains capped to ~2/3 world height and gentled (ridged amplitude/frequency lowered), snow line lowered to match. Centralization: ~27 world-gen/render tuning constants (biome amplitudes & frequencies, climate-noise frequencies/octaves, biome-selection thresholds, blend width, cell size, filler depth, snow line, camera near plane, spawn offset, overlay scale) hoisted from scattered literals into a region-organized, fully-commented Configuration. Configuration is threaded into NoiseSource, the biomes, BiomeRegistry, BiomeMap (+Classify), TerrainSampler, WorldGenerator (+BlockAt filler depth), and Camera via Player. Defaults equal the prior values, so generation is unchanged; worldgen tests updated for the new constructor signatures.
209 lines
8.4 KiB
C#
209 lines
8.4 KiB
C#
namespace VoxelEngine.Core;
|
||
|
||
using OpenTK.Mathematics;
|
||
|
||
public sealed class Configuration
|
||
{
|
||
#region -- World --
|
||
|
||
// World generation seed. null → a fresh random seed each run; set a value for
|
||
// a reproducible world.
|
||
public int? Seed { get; set; } = null;
|
||
|
||
// Blocks above the terrain surface at (0,0) where the player spawns.
|
||
public float SpawnHeightOffset { get; set; } = 2f;
|
||
|
||
#endregion -- World --
|
||
|
||
#region -- Rendering & View --
|
||
|
||
// Horizontal view radius in chunks (Chebyshev). Drives how far terrain loads
|
||
// and the fog / far-plane distance. Higher = see further, much heavier load.
|
||
public int RenderDistanceHorizontal { get; set; } = 8;
|
||
|
||
// Camera vertical field of view, in degrees.
|
||
public float Fov { get; set; } = 60f;
|
||
|
||
// Near clip plane distance (world units); anything nearer is not drawn.
|
||
// (The far plane is derived from RenderDistanceHorizontal over in Player.)
|
||
public float CameraNearPlane { get; set; } = 0.1f;
|
||
|
||
// Distance fog begins at this fraction of the fog-end distance (fog end is
|
||
// derived from RenderDistanceHorizontal). 0.7 → fog starts at 70% of the edge.
|
||
public float FogStartFraction { get; set; } = 0.7f;
|
||
|
||
// Sky / clear colour, also the distance-fog target colour (RGB, 0–1).
|
||
public Vector3 SkyColor { get; set; } = new(0.45f, 0.65f, 0.95f);
|
||
|
||
#endregion -- Rendering & View --
|
||
|
||
#region -- Window --
|
||
|
||
// Initial window size in pixels.
|
||
public int WindowWidth { get; set; } = 1280;
|
||
public int WindowHeight { get; set; } = 720;
|
||
|
||
#endregion -- Window --
|
||
|
||
#region -- Chunk Streaming --
|
||
|
||
// Horizontal radius (chunks) around spawn that must finish loading before the
|
||
// loading screen clears.
|
||
public int SpawnReadyRadiusHorizontal { get; set; } = 1;
|
||
|
||
// Max chunk generate/mesh jobs running on worker threads at once.
|
||
public int MaxGenerateJobsInFlight { get; set; } = 8;
|
||
|
||
// Max finished chunk meshes uploaded to the GPU per frame (caps per-frame hitches).
|
||
public int MaxMeshUploadsPerFrame { get; set; } = 4;
|
||
|
||
// Background worker threads used for chunk generation/meshing.
|
||
public int WorkerThreadCount { get; set; } = Math.Max(1, Environment.ProcessorCount / 2);
|
||
|
||
// Multiplier applied to (dy)² in chunk-load priority. >1 prioritizes chunks at
|
||
// the player's Y over equally-distant chunks above/below, so the visible
|
||
// surface fills in before far-underground / overhead chunks.
|
||
public int VerticalPriorityWeight { get; set; } = 4;
|
||
|
||
#endregion -- Chunk Streaming --
|
||
|
||
#region -- Player & Controls --
|
||
|
||
// Movement speed, in blocks per second.
|
||
public float MoveSpeed { get; set; } = 8f;
|
||
|
||
// Mouse-look sensitivity (degrees of rotation per pixel of mouse movement).
|
||
public float MouseSensitivity { get; set; } = 0.15f;
|
||
|
||
#endregion -- Player & Controls --
|
||
|
||
#region -- World Gen: Terrain Shape --
|
||
|
||
// Average width in blocks of one biome region (Voronoi cell). Larger = bigger,
|
||
// fewer biomes.
|
||
public float BiomeCellSize { get; set; } = 960f;
|
||
|
||
// Blocks over which terrain height eases from one biome to its neighbour across
|
||
// their shared border. Larger = gentler, wider transitions.
|
||
public float BiomeBlendWidth { get; set; } = 128f;
|
||
|
||
// Filler layers (dirt/sand) placed directly below the surface block before the
|
||
// biome's solid under-material (usually stone) begins.
|
||
public int SurfaceFillerDepth { get; set; } = 3;
|
||
|
||
#endregion -- World Gen: Terrain Shape --
|
||
|
||
#region -- World Gen: Climate Noise --
|
||
// Low-frequency fields that decide biome placement. Lower frequency = larger,
|
||
// smoother climate regions; more octaves = more fine variation.
|
||
|
||
// Elevation field — high values become Mountains, low values lowland.
|
||
public float ContinentFrequency { get; set; } = 0.0035f;
|
||
public int ContinentOctaves { get; set; } = 4;
|
||
|
||
// Temperature field — high values become Desert.
|
||
public float TemperatureFrequency { get; set; } = 0.0015f;
|
||
public int TemperatureOctaves { get; set; } = 3;
|
||
|
||
// Forest-density field — high values become Forest (else Plains).
|
||
public float ForestFrequency { get; set; } = 0.02f;
|
||
|
||
#endregion -- World Gen: Climate Noise --
|
||
|
||
#region -- World Gen: Biome Selection --
|
||
// Thresholds on the climate fields (values ≈ -1..1), tested in order:
|
||
// mountains → desert → forest → plains.
|
||
|
||
// Elevation at/above which a cell is Mountains.
|
||
public float MountainsElevationThreshold { get; set; } = 0.25f;
|
||
|
||
// Temperature above which a non-mountain cell is Desert.
|
||
public float DesertTemperatureThreshold { get; set; } = 0.33f;
|
||
|
||
// Minimum temperature for Forest (colder than this → Plains).
|
||
public float ForestTemperatureThreshold { get; set; } = -0.33f;
|
||
|
||
// Minimum forest-density for Forest (below this → Plains).
|
||
public float ForestDensityThreshold { get; set; } = 0f;
|
||
|
||
#endregion -- World Gen: Biome Selection --
|
||
|
||
#region -- World Gen: Biome Surface Heights --
|
||
// Per biome: surfaceHeight = SeaLevel + ContinentAmplitude·continentNoise
|
||
// + DetailAmplitude·detailNoise. Amplitudes are in blocks; detail frequency
|
||
// sets the bumpiness scale (higher = smaller, choppier features).
|
||
|
||
// Plains — gentle rolling grassland.
|
||
public float PlainsContinentAmplitude { get; set; } = 24f;
|
||
public float PlainsDetailAmplitude { get; set; } = 8f;
|
||
public float PlainsDetailFrequency { get; set; } = 0.01f;
|
||
|
||
// Forest — like plains, a touch hillier.
|
||
public float ForestContinentAmplitude { get; set; } = 24f;
|
||
public float ForestDetailAmplitude { get; set; } = 16f;
|
||
public float ForestDetailFrequency { get; set; } = 0.01f;
|
||
|
||
// Desert — flat with low dunes.
|
||
public float DesertContinentAmplitude { get; set; } = 16f;
|
||
public float DesertDetailAmplitude { get; set; } = 6f;
|
||
public float DesertDetailFrequency { get; set; } = 0.008f;
|
||
|
||
// Mountains — tall ridged peaks (uses ridged noise instead of a smooth detail
|
||
// field). Peaks roughly cap at SeaLevel + ContinentAmplitude + RidgedAmplitude.
|
||
public float MountainsContinentAmplitude { get; set; } = 40f;
|
||
public float MountainsRidgedAmplitude { get; set; } = 45f;
|
||
public float MountainsRidgedFrequency { get; set; } = 0.005f;
|
||
public int MountainsRidgedOctaves { get; set; } = 4;
|
||
// World-Y at/above which mountain tops render as snow.
|
||
public int MountainsSnowLine { get; set; } = 270;
|
||
|
||
#endregion -- World Gen: Biome Surface Heights --
|
||
|
||
#region -- Cave Generation --
|
||
|
||
// Spatial frequency of the 3D simplex cave-density field; higher = smaller,
|
||
// more frequent pockets.
|
||
public float CaveNoiseFrequency { get; set; } = 0.03f;
|
||
|
||
// Density cutoff below which a solid voxel becomes air; higher = more cave.
|
||
public float CaveNoiseThreshold { get; set; } = -0.3f;
|
||
|
||
// Edge length (blocks) of a worm-spawn grid cell; one worm candidate per cell.
|
||
public int WormCellSize { get; set; } = 64;
|
||
|
||
// Per-cell chance out of 1000 that a worm spawns; 300 = 30%.
|
||
public int WormSpawnProbabilityPermille { get; set; } = 300;
|
||
|
||
// Number of trace steps (≈ blocks) a worm travels.
|
||
public int WormMaxLength { get; set; } = 80;
|
||
|
||
// Worm tunnel radius bounds; interpolated + sine-modulated along the path to
|
||
// form bulges/chambers.
|
||
public float WormMinRadius { get; set; } = 1.5f;
|
||
public float WormMaxRadius { get; set; } = 3.5f;
|
||
|
||
// Ceiling: caves carve only at or below this world-Y ("no caves above").
|
||
// Default 256 = SeaLevel → caves stay below sea level, keeping the taller
|
||
// surface terrain solid. Raise toward WorldHeight-1 to allow surface caves.
|
||
public int MinCaveY { get; set; } = 256;
|
||
|
||
#endregion -- Cave Generation --
|
||
|
||
#region -- Cave Lighting --
|
||
// Underground darkening: brightness fades from CaveDarkStartY down to
|
||
// CaveDarkEndY, never dropping below CaveMinBrightness.
|
||
|
||
public float CaveDarkStartY { get; set; } = 264f; // WorldConstants.SeaLevel + 8
|
||
public float CaveDarkEndY { get; set; } = 224f; // WorldConstants.SeaLevel - 32
|
||
public float CaveMinBrightness { get; set; } = 0.15f; // floor brightness deep underground (0–1)
|
||
|
||
#endregion -- Cave Lighting --
|
||
|
||
#region -- Debug Overlay --
|
||
|
||
// Pixel size of each font "pixel" in the on-screen debug text (biome + coords).
|
||
public int DebugOverlayTextScale { get; set; } = 3;
|
||
|
||
#endregion -- Debug Overlay --
|
||
}
|