A practical proof-of-concept for DEM-trained procedural terrain generation.
Goal:
real DEM corpus
-> paired DEM tiles
-> train residual terrain detailer
-> generate DEM-like fictional terrain
-> render / QA / export
This POC intentionally starts with a conditional residual U-Net, not a giant diffusion model. Diffusion is the next spicy step after the boring model beats bicubic upscaling plus fractal nonsense.
The first useful model should answer:
Given a coarse macro terrain heightmap, can we add believable real-world DEM-style detail?
Training target:
input = coarse/upscaled terrain + derivative channels
target = high-res terrain residual
output = predicted residual
final = coarse + predicted residual
This gives us control, low VRAM use, objective metrics, and a direct Minecraft terrain pipeline.
This does not need real DEM data. It generates fake DEM-ish tiles so you can test the training loop.
python scripts/make_synthetic_dataset.py --out data/synthetic --count 256 --size 256
python scripts/train_residual_unet.py --config configs/residual_unet_smoke.yaml
python scripts/sample.py --checkpoint outputs/checkpoints/best.pt --data data/synthetic/val --out outputs/samples
python scripts/render_heightmap.py --input outputs/samples/sample_000_pred.npy --out outputs/renders/sample_000_pred.pngPut GeoTIFF DEM files under:
data/raw/
Then:
python scripts/build_tiles.py --src data/raw --out data/tiles --tile-size 512 --stride 256 --downscale 8Expected split:
data/tiles/train/*.npz
data/tiles/val/*.npz
Each tile .npz contains:
x: model input, shape[C,H,W]y: residual target, shape[1,H,W]target: normalized high-res height, shape[1,H,W]coarse: normalized coarse/upscaled height, shape[1,H,W]meta: JSON string metadata
- Use real region-level validation splits. Do not randomly split neighboring tiles from the same mountain into train and val unless you want your validation score to lie like a used car salesman.
- Keep absolute elevation metadata, but train mostly on normalized local shape.
- Start 256x256 for smoke tests, then 512x512.