Texture Dune Field
Sand dunes on demand — an aeolian texture that tiles
- image
- mask
- dune_info
Desert floors, rippled sand, wind-blown ridges - if you've ever tried to get a believable sand texture out of a diffusion model, you know it gives you a generic tan blur and a seam you can't kill. Texture Dune Field sidesteps both problems: it's a procedural generator that draws the dunes itself, and like every field node in this pack it's seamless by construction. It's the node you reach for when a roughness map or an albedo base needs to read as "sand" and the geometry of that sand actually matters.
How it works
Under the hood it's the same wrapped-noise machinery as the pack's Noise Field, bent into dune shapes. The procedural_dune_pattern core layers a low-frequency drift field (the big dune forms) with a higher-frequency ripple detail field (the wind texture on top), then shapes the result with crest_sharpness, which controls how crisp the dune ridges are. direction_deg rotates the whole pattern, and wind_skew leans the ripples the way wind actually stacks sand.
Three pattern_mode options give you the dune typography: ridges (parallel wind-built ridges, the default), sheet (broad rolling sheets of sand), and crescent (barchan-style crescent dunes). drift_strength pushes how much the pattern bends downwind. Everything is deterministic on seed and generated in numpy - no model, no GPU, instant.
The inputs that matter
Like the rest of the pack's generators, all settings sit in one settings_json text box rather than sliders. The defaults are a decent starting point; the ones you'll actually touch:
pattern_mode- ridges / sheet / crescentdune_scale_px- how big the dunes are (184 px default)direction_degandwind_skew- orientation and how much the wind bends the ripplescrest_sharpnessandripple_detail- ridge sharpness versus sand-grain textureseed- swap it to get a different layoutcontrast/balance/invert- tonal shaping
Outputs are the standard trio: an image (grayscale field as RGB - wire it into a texture input directly), a mask (the same field as a single channel, your height/bump feed), and a dune_info string logging what ran. Because the output is seamless, you can also skip the whole detile/seamless pass downstream - it never has a seam to fix.
Installing it
This ships in MKRShift Nodes from criskb. Via ComfyUI Manager, search "MKRShift Nodes" and install, or:
cd ComfyUI/custom_nodes
git clone https://github.com/criskb/MKRShift_Nodes
Restart ComfyUI and it appears under MKRShift Nodes → Surface → Texture. No models, no pip extras - it's numpy/Pillow/torch only, which you already have. (The README's ffmpeg and 3D-slicer mentions are for the pack's video and G-code lanes; nothing here needs them.)
Common gotchas
This pack is new - essentially zero impressions and no community lore yet - so treat the code as the source of truth. The big one: malformed JSON in settings_json silently reverts to defaults instead of erroring, and out-of-range values get clamped. If your dunes don't match what you typed, re-check the JSON first. Also note the 1024×1024 default: at dune_scale_px 184 that's roughly 5–6 dunes across, which reads well for a tile. Drop the scale if you want finer sand.
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| settings_json | STRING | {"width":1024,"height":1024,"pattern_mode":"ridges","dune_scale_px":184.0,"direction_deg":18.0,"wind_skew":0.36,"crest_sharpness":0.54,"ripple_detail":0.34,"drift_strength":0.28,"contrast":1.16,"balance":0.0,"invert":false,"seed":109} | — |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| image | IMAGE | — |
| mask | MASK | — |
| dune_info | STRING | — |