- C# 95.4%
- HTML 2.4%
- Python 1.5%
- Shell 0.7%
| .forgejo/workflows | ||
| build | ||
| release | ||
| Strata | ||
| Strata.Diffusion | ||
| Strata.Diffusion.Cli | ||
| tools | ||
| .gitignore | ||
| Directory.Build.props | ||
| LICENSE | ||
| MODEL_SHA256SUMS.txt | ||
| README.md | ||
| Strata.sln | ||
| THIRD_PARTY_NOTICES.md | ||
Strata
Strata is a Vintage Story 1.22 world-generation mod that replaces the initial vanilla terrain height fill with the infinite terrain-diffusion ONNX pipeline. Vintage Story still performs its normal rock-strata, cave, ore, soil, vegetation, and structure generation afterward. Vintage Story's latitude-driven temperature remains authoritative and conditions the model in realistic-climate worlds; the model supplies the precipitation field. Clients do not need to install the mod; an optional client installation adds directional river animation when experimental Rivers V4 is enabled.
Building from source
Strata compiles against Vintage Story's own assemblies. tools/fetch_vintage_story.sh downloads
them from the official CDN — the Linux server tarball, which carries every referenced assembly, is
far smaller than a game install and needs no account:
export VINTAGE_STORY="$(tools/fetch_vintage_story.sh)" # or: tools/fetch_vintage_story.sh 1.22.5
dotnet build Strata.sln -c Release
Passing no version resolves the current stable release from api.vintagestory.at. The script is
idempotent, so re-running it reuses an existing download of the same version. If you already have
the game installed, just point VINTAGE_STORY at that directory instead.
.forgejo/workflows/build.yml runs the same steps in CI on a docker runner and publishes all
three packages. It also reports, without failing the build, when the latest stable Vintage Story
release has moved past the version declared in Strata/modinfo.json.
One ModDB-compatible ZIP with Windows GPU acceleration
Build the release package:
dotnet build build/Strata.Package.proj -t:PackageUniversalDirectML
This produces artifacts/packages/Strata-0.4.1-universal-directml.zip (36,366,053 bytes), below the
Vintage Story ModDB 40 MB limit. Install it directly in the server or single-player Mods directory;
do not unpack it. Windows x64 uses DirectML on DirectX 12 GPUs from NVIDIA, AMD, or Intel. Windows
Arm64, Linux x64/Arm64, and Apple Silicon retain CPU-capable runtimes in the same ZIP. auto falls
back to CPU if an accelerator cannot create a model session.
The compact Windows runtime uses the DirectML component supplied by supported Windows versions;
Windows 10 version 1903 or newer and a DirectX 12-capable GPU are required for acceleration. The
large CUDA developer build remains available with -t:PackageUniversalAccelerated, but its native
libraries make it about 431 MB and therefore unsuitable for ModDB. The CPU-only universal target
and per-platform Package/PackageAll targets remain available for testing.
What the CUDA package requires
The CUDA package (Strata-<version>-universal-accelerated.zip) bundles ONNX Runtime 1.27.1's CUDA
provider but not the CUDA libraries themselves, which remain a system dependency. Most Windows
users should prefer the DirectML package instead: it needs none of the following, works on AMD and
Intel GPUs too, and is a tenth of the download.
- Windows x64 or Linux x64. No CUDA build exists for Windows Arm64, Linux Arm64, or macOS; those platforms fall back to the CPU runtime inside the same ZIP.
- An NVIDIA GPU of Turing generation or newer. The provider is compiled for compute capabilities 7.0, 7.5, 8.0, 8.6, 8.9, 9.0, 10.0 and 12.0 — that is Volta, Turing (GTX 16 / RTX 20), Ampere (RTX 30), Ada (RTX 40), Hopper and Blackwell (RTX 50). Pascal (GTX 10 series) and older are not supported, because CUDA 13 dropped them; those cards must use DirectML or CPU.
- CUDA 13.x runtime libraries. The provider links
libcudart.so.13,libcublas.so.13,libcublasLt.so.13,libcufft.so.12andlibcurand.so.10(cublas64_13.dll,cublasLt64_13.dll,cufft64_12.dllon Windows). CUDA 12 is not sufficient. - cuDNN 9.x (
libcudnn.so.9/cudnn64_9.dll). - An NVIDIA driver new enough for CUDA 13. Check NVIDIA's CUDA release notes for the minimum version for your platform; installing a current driver is the simplest route.
- Free VRAM. The base model's weights alone are 2.0 GB in FP32, so allow roughly 4 GB of free VRAM in addition to whatever the game itself is using.
The libraries must be discoverable at load time — on the default PATH on Windows, or on the loader
path on Linux. Installing the CUDA Toolkit and cuDNN handles this. If a CUDA session cannot be
created, InferenceDevice: "auto" logs the reason and falls back to CPU rather than failing
generation, so a missing dependency shows up as slow terrain rather than a crash. Use
InferenceDevice: "cuda" to require it and get a hard error instead.
The models are intentionally separate from the mod ZIP. On first uncached terrain generation,
Strata downloads five files totaling about 2.3 GB directly over HTTPS from Alexander Goslin's
official Hugging Face ONNX repository.
They are stored in the game data directory's StrataModels folder and reused for all worlds. Set
AutoDownloadModels to false if you prefer to install the files manually.
Release downloads are pinned to immutable Hugging Face revision
ad2df557eca5645f588766101cf3bc3682455c3e. Strata verifies the expected byte length and SHA-256
of every official file before first use and refuses to load a mismatch. Successful verification is
remembered beside each model; the published values are in MODEL_SHA256SUMS.txt and in the ZIP's
licenses folder. ONNX files are model graphs/weights rather than game plugins, and no
data is uploaded during inference; they are nevertheless large third-party inputs to ONNX Runtime,
so manual installation with AutoDownloadModels=false remains available for cautious servers.
World height
Set the world height to 512 on Vintage Story's create-world screen. For a dedicated server, set
MapSizeY to 512 before creating the save. A code mod is initialized only after Vintage Story
has fixed the new save's vertical chunk layout, so Strata warns about a mismatch but does not risk
resizing a world. Existing worlds cannot be safely resized.
The configured WorldHeight is the recommended/expected height used by that warning. Heights are
made of 32-block vertical chunks, and taller worlds cost additional vanilla worldgen time even when
the terrain surface stays at the same elevation.
Performance and diagnostics
Run this as a server administrator while chunks are generating:
/strata stats
It reports pipeline state, each model's actual ONNX provider, generated/fallback chunk counts, Strata block-fill time, cache hit rates, tile bakes and queue depth, and per-model inference time. The startup log reports the platform, world height, effective settings, model readiness, and confirms that downstream vanilla cave/worldgen passes remain active.
Useful settings in VintagestoryData/ModConfig/strata.json:
TerrainStyle:realisticpreserves the existing official terrain distribution and remains the default.fantasyreorganizes macro elevation into stronger ridge systems and selectively raises established highlands.extrememakes those systems more frequent and amplifies them further. Every style still uses the full-resolution base and decoder models, vanilla caves, and the plains shaping pass.InferenceDevice: leave this atautoto use DirectML automatically on Windows x64 and CPU or the available platform provider elsewhere. Usedirectmlto require DirectML, orcputo disable GPU inference.gpurequires any usable GPU provider and reports a clear error if none works.GpuDeviceId: DirectML/CUDA adapter index, normally0.
Apple Silicon GPU (Metal via WebGPU)
The base model dominates generation time and previously produced garbage terrain on ONNX Runtime's WebGPU provider (Dawn → Metal). The cause is a WebGPU convolution bug that only affects an input with exactly 6 channels; 3, 5, 7, 8, 12 and 16 channels all match the CPU provider. Exactly one of the base model's 95 convolutions hits that shape — the first one — so its error propagated through the whole network.
tools/make_webgpu_base_model.py widens that single convolution from 6 to 8 input channels by
appending zero channels to both its input and its weight. The added terms contribute exactly zero,
so the patched model is bit-identical to the original on the CPU provider; nothing is retrained
or quantized.
python3 tools/make_webgpu_base_model.py models/base_model.onnx models/base_model_webgpu.onnx
Then select it with ModelVariant: "custom" and CustomBaseModelFile: "base_model_webgpu.onnx",
and send only the base model to WebGPU via STRATA_DEV_BASE=webgpu.
Measured on an Apple M2, one 128-block tile including drainage and carving: 98.7 s → 24.8 s, with an identical elevation range and identical river output. Keep the coarse model on CoreML and the decoder on CPU — the decoder is independently wrong on WebGPU (a different defect, since it has no 6-channel convolution) and running it there corrupts elevations. Because GPU and CPU accumulate in different orders, WebGPU-generated terrain differs from CPU terrain by roughly 1e-6 m; that is far below one block and cannot produce a visible seam, but it is not bit-reproducible across providers.
ModelVariant:fp32selects the official models and remains the default.fp16selects localbase_model_fp16.onnx,coarse_model_fp16.onnx, anddecoder_model_fp16.onnxfiles.autoprefers that complete local FP16 set and otherwise uses FP32.customuses the five configurableCustom*Filenames.InferenceBatchSize: batches independent windows without reducing resolution or diffusion steps. CPU-heavy model stages automatically remain at batch 1 because batching was slower there.TileChunks: larger tiles reuse more intermediate work, but the first new tile takes longer.MemoryCacheTiles: bounded in-memory LRU for baked heightmaps.DiskCache: reuses deterministic baked tiles after restarts.PrefetchRadius: defaults to 0 so background model work cannot block an urgently requested tile. Try 1 only when the server has spare inference capacity.IntraOpThreads: defaults to 0, letting ONNX Runtime choose its CPU thread pool.SummitCompressionHeadroom: defaults to 96 blocks. Model elevations entering this top band are progressively compressed toward the ceiling instead of hard-clipped, retaining distinct summits and ridges rather than producing large flat top-of-world plateaus. Set it to 0 for the old clamp.ExposeMountainRock: defaults to true. After the normal block-layer pass, sufficiently steep mountain surfaces reveal Vintage Story's locally selected rock type instead of remaining fully soil-covered.MountainRockMinHeightAboveSeaLevel,MountainRockFullHeightAboveSeaLevel,MountainRockReliefRadius, and the twoMountainRock*Reliefsettings tune that transition.ExperimentalRivers: defaults to false. Rivers V4 builds deterministic macro drainage plans, routes ocean-connected channels downhill, turns each macro reach into a slope-aware meander, then rasterizes it as a noise-warped distance field: a valley is drawn down around each reach before the channel itself is carved with a monotonically descending freshwater surface.RiverValleyWidthBlocksandRiverValleyRiseMeters: default to 48 blocks and 120 meters, the width of the valley beside each channel and how far its floor climbs toward the rim. The valley only ever lowers terrain and its weight reaches zero at the rim, so flat country is untouched and coastlines cannot be cut below sea level. Set the width to 0 for the old narrow shoulders.RiverBankNoiseStrengthandRiverBankNoiseFrequency: default to 22 blocks and 0.006, warping the bank outline so channel edges wander instead of tracing the planned polyline. Set the strength to 0 for geometrically straight banks.RiverGravelBanks: defaults to true, replacing block-layer soil withinRiverGravelReachBlocks(default 10) of a channel with the locally correct gravel variant, giving rivers gravel beds and banks. The affected width is noise-modulated, so the gravel edge does not trace the channel.RiverMacroRegionCells: defaults to 32, an 8,192×8,192-block drainage plan. Larger values plan farther at once but increase the one-time coarse-model cost. Synthetic terminal lakes are off by default;ExperimentalRiverLakesandRiverLakeGoalsPerRegionopt into the unfinished behavior.RiverMinimumDropMetersPerMacroCellandRiverMaximumDropMetersPerMacroCellbound the water surface drop per 256 horizontal blocks. At the default 15 meters per VS block, shallow gradients appear as periodic one-block steps instead of a perfectly flat water plane.RiverVisualFlowSpeed: controls optional client-side directional water animation. Clients that do not install Strata still see ordinary water and can join normally.RiverPhysicalFlowStrength: controls the server-authoritative current applied to entities in river columns. Set it to 0 to retain visual/elevation flow without entity drift.RiverHydrologyHalo: retained only so older configuration files remain readable; regional rivers no longer treat independently generated tile edges as drainage outlets.RiverFlowThreshold: defaults to 1400 precipitation-weighted upstream cells. Lower values add more headwater streams.RiverMaxWidthBlocks,RiverMinDepthBlocks,RiverMaxDepthBlocks, andRiverMinElevationMeterscontrol the channel geometry.PlainsSmoothing: defaults to 0.65. Set it from 0 to 1 to control how strongly naturally low-relief inland terrain is blended toward a broader, gentler surface. Set it to 0 for the raw model output.PlainsSmoothingRadius: defaults to 16 blocks. Larger values make broader plains and add a correspondingly larger seamless halo to each tile request.PlainsMaxReliefMeters: defaults to 180. Lower values protect more hills; higher values allow smoothing to affect rougher rolling terrain.PlainsCoastProtectionMeters: defaults to 90, fading the filter out near sea level so coastlines, beaches and small islands retain their model detail.
Strata downloads only the validated official FP32 set. FP16 and custom weights are local-only and must preserve the official tensor names, shapes, and float32 inputs/outputs. They may use reduced precision internally. The selected variant and configured file paths are included in the disk-cache identity, so different configured sets do not silently share baked heightmaps.
The terrain style is also part of the disk-cache identity. Pick a style before exploring a new world: changing it later cannot reshape chunks that Vintage Story has already saved and will create a border between old and newly generated terrain.
No model resolution or diffusion step count is reduced. The optional plains pass runs after full-detail inference and intentionally softens only low-relief terrain; mountains and protected coasts retain the original model elevation. Its settings are part of the disk-cache filename, so a changed profile cannot silently reuse a differently filtered height tile. Change shaping settings only before creating a world or expect borders against chunks that were already generated.
Mod compatibility
- Terrain Slabs 1.0.17: expected to be compatible. It runs a later world-generation pass that
replaces suitable exposed blocks with slabs rather than replacing
GenTerra. Terrain Slabs and its required PlaceOnSlabs dependency are both-side mods, so install them on the server and clients. This combination still needs longer playtesting. - Algernon's Watersheds: incompatible. Both mods change
GenTerra; Strata detects mod IDwatersheds, logs a prominent error, and leaves its own terrain patch inactive to prevent broken generation. Remove one of the two mods and use a new world rather than trying to solve it through load order. - Rivers: incompatible in its current form. Rivers disables vanilla
GenTerraand supplies a complete replacement, while Strata supplies its own terrain heights. Strata detects mod IDriversand leaves its patch inactive instead of allowing two terrain generators to collide. The two cannot be reconciled by load order: Rivers seeds river mouths from Vintage Story's own ocean noise and grows channels inland from them, whereas Strata's coastlines come from the diffusion model, so its mouths would land inland. Strata instead adapts the MIT-licensed VSRiverGen fork's channel rasterization and gravel banks on top of its own drainage routing; seeTHIRD_PARTY_NOTICES.md.
The Terrain Diffusion models provide elevation and climate fields, but no river-channel output. Strata therefore derives a deterministic regional drainage graph from the model's coarse elevation and precipitation fields. Priority-flood routing connects ocean catchments before any detailed tile is carved, so cache-tile order cannot invent arbitrary river ends. A cached slope-aware subdivision adds continuous local bends without another model call; broad low-gradient reaches meander more than steep reaches. Full-detail carving stores the descending surface and downstream vector with each tile. Treat this as an experimental new-world feature; changing its settings cannot recarve saved chunks.
Preliminary benchmark
In a packaged Vintage Story 1.22.3 server smoke test on an Apple M2 with a 512-block world, Strata processed 225 terrain callbacks with zero fallbacks and baked four diffusion tiles in about 90 seconds. The cache reached a 98.2% hit rate, while Strata's block fill used only 11 ms. ONNX time was about 53 seconds for base, 36 seconds for decoder, and 1 second for coarse; coarse used CoreML while base and decoder used CPU. Model loading took 12.8 seconds. A separate 64x64 deterministic regression sample took about 35 seconds, and optimized/baseline outputs were byte-for-byte identical.
On an RTX 5070 Ti with a Ryzen 9800X3D, all three models resolved to DirectML. A mixed-cache test generated 23 new tiles in 10 seconds of pipeline time (16 seconds bake wall time), with 1,429 chunks reported at 1m38s uptime, 98.4% cache hits, and zero fallbacks or failures. Eleven additional tiles were loaded from disk, so this should not be presented as a fully cold benchmark.
Development
dotnet build Strata.sln
Cross-builds need a local Vintage Story installation for compile-time API references. If it is not
in a standard location, set VINTAGE_STORY to the directory containing VintagestoryAPI.dll.
The Vintage Story integration is organized by responsibility under Strata/: Configuration,
Caching, Generation (including Hydrology and surface rules), and Patches. The diffusion
runtime remains isolated in Strata.Diffusion.
AI assistance
I designed and wrote Strata. I used AI tools as supporting aids for research, occasional code completion, polishing descriptions and documentation, and drafting some code comments. I reviewed and tested the changes and am responsible for the released code.
Credits
The diffusion pipeline and 30 m/px models are based on Alexander Goslin's
Terrain Diffusion and
ONNX model release. See
THIRD_PARTY_NOTICES.md and the packaged licenses directory for licenses and attribution.
License
Strata's original code and documentation are licensed under the Apache License 2.0. Bundled and adapted third-party components retain their original licenses as documented in THIRD_PARTY_NOTICES.md.