Open-source project
majidmanzarpour/threejs-procedural-dungeon avatar
majidmanzarpour/threejs-procedural-dungeon

Dungeon Forge: a deterministic Three.js dungeon generator you can watch build itself

Real-time procedural dungeon generator in Three.js - deterministic seeds, Delaunay/MST graph layouts, room semantics, five themes, and a custom bloom/tilt-shift pipeline.

500 stars82 forksJavaScriptMIT

At a glance

What is it?
Dungeon Forge runs a seeded scatter, separate, Delaunay, MST, carve and decorate pipeline in the browser and renders the result with Three.js. It is a demo and a reference implementation, not a game engine, and its README is candid about the fact that it is one big module.
Who is it for?
Dungeon Forge is for people who want to read a working generation pipeline end to end, or to show a seeded dungeon rebuilding itself in a browser. It is not for teams that need a library they can import into an existing engine, because the generator and renderer share one module and one RNG stream.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 74 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 17, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What Dungeon Forge actually solves

Most procedural dungeon code you find online is either a pure algorithm with no visual output, or a finished game with the generator buried inside it. Dungeon Forge sits in the middle. It is a browser page that runs the generation pipeline and draws the result, and it exposes the intermediate stages so you can see them. The README describes the sequence as scatter, separate, Delaunay, MST plus loops, semantics, carve, rasterize plus BFS, decorate, and it says each step lights up in the HUD as it happens.

The audience is narrow but real. If you are writing your own roguelike and want a reference for how a Delaunay graph becomes a tile grid with doorways and a difficulty ramp, this is readable source. If you are teaching or presenting procedural generation, the graph overlay and the difficulty heatmap are useful because they render the abstract structures in world space rather than in a diagram. If you want a dungeon in your shipped game, you will be copying code rather than importing a dependency.

One RNG stream threaded through every stage

The mechanism that makes the demo reproducible is a single mulberry32 stream. The README states that the same stream is threaded through every stage, from scatter to decoration, so a seed rebuilds the same map down to the last torch. That is a stronger guarantee than seeding each stage separately, because it means the number of random draws consumed by an early stage cannot desynchronise a later one.

The layout itself is graph-based. Room centres are Delaunay-triangulated to produce candidate connections, then reduced to a minimum spanning tree so the dungeon is guaranteed fully connected. A tunable fraction of the leftover Delaunay edges is added back as loops, which is what stops the result from looking like a spanning-tree spider. After that, a breadth-first search from the entrance assigns depth and difficulty and tags rooms as entrance, combat, elite, treasure, shrine or boss. Carving stamps rooms and L-shaped corridors into a tile grid, and the rasterise pass walks that grid to place walls, doorways and edge trims and to compute per-tile shading.

The trade-off is that the RNG is shared state. Any change to how many draws a stage consumes will change every downstream stage for the same seed. That is fine for a demo, and awkward if you want to swap one stage out.

Installing Dungeon Forge and forging a first dungeon

The README gives a two-command quick start. Node 18 or later is required. The package is not published as a library, so this is a clone-and-run workflow rather than an install from a registry.

bash
npm install
npm run dev        # http://localhost:5173

Vite serves the page on port 5173. You should see the control panel in the top-left and a dungeon already building. Type a seed into the seed field or use the dice button, then press FORGE DUNGEON, or press R, to rebuild. The same seed produces the same map.

bash
npm run build
npm run preview    # serve the production build locally

The build emits a static bundle in dist/. The README says that folder can be dropped on any static host, naming Netlify, GitHub Pages, itch.io or a plain folder. The preview server runs on port 4173.

The controls are worth learning before you judge the output. G toggles the graph overlay, which draws the Delaunay edges, the MST and the loops in world space. H toggles the difficulty heatmap. P toggles the post-processing stack for an A/B comparison, and space skips the build animation. The panel's rooms, loopiness and decor density sliders each trigger a re-forge.

The single-module design is the main constraint

The README is explicit that the generator and the renderer live in one self-contained src/main.js, and it explains why: shared RNG, materials, geometry caches and render targets. The project structure lists only index.html, src/main.js, src/ui/styles.css, docs/preview.jpg and public/og.jpg. There is no separate generator module to import.

That is a genuine limitation, not a packaging detail. You cannot take the layout algorithm and run it headless in Node without first untangling it from Three.js materials and render targets. You cannot unit-test the carving stage in isolation. And because the RNG is shared, extracting one stage changes the output of every other stage unless you reproduce the exact draw order.

The README acknowledges the coupling directly, saying the system reads best as one module. For a demo that is a defensible choice. For anyone hoping to drop the generator into an existing engine, it means a refactor before the first useful line of integration.

Where Dungeon Forge is the wrong tool

If your target is Unity, this project will not help you directly. The related searches around Unity dungeon generation point at a different ecosystem, and Dungeon Forge is JavaScript and Three.js with a Vite build. The algorithms transfer, since Delaunay triangulation and minimum spanning trees are not engine-specific, but the code does not.

There are other cases where it is the wrong fit. If you need a runtime generator that produces dungeons during play at a fixed frame budget, the README's live readouts include generation time alongside FPS and draw calls, which suggests generation is treated as something you watch rather than something you hide. If you need server-side generation for authoritative multiplayer, the browser and WebGL dependency is in the way. And if you need a stable API with versioned releases, note that no releases were retrieved for this repository, so there is no release history to pin against. The last push was on 2026-07-05.

How it differs from a Unity dungeon generator

The comparison that matters is with the Unity-style generators the search results point to, such as Vazgriz's widely referenced approach. Those projects are typically built around a grid or a set of predefined room prefabs, and they plug into Unity's scene and prefab system. Connectivity is usually handled by a corridor algorithm over that grid, and the visual result comes from artist-made assets.

Dungeon Forge inverts several of those choices. Rooms are not prefabs on a grid; they are rectangles sampled in a rough disc and pushed apart by relaxation passes until they stop overlapping. Connectivity is not a corridor walk over a grid; it is a Delaunay graph reduced to an MST and then re-looped. And nothing is loaded from disk: the README states that stone, cracks, runes, portals and light shafts are generated to canvas textures at load, and that geometry is built from primitives.

The practical difference is what you get out. A prefab-based Unity generator gives you a layout that already looks like a game because the assets carry it. Dungeon Forge gives you a layout plus a rendering treatment, and the treatment is inseparable from the generator in the current code.

Licence and the cost of keeping up

The repository is MIT licensed, and package.json declares the same. MIT is permissive, so reuse in a commercial product is generally permitted provided the copyright notice and licence text are retained, but that is a description of the licence text and not legal advice. Check the LICENSE file in the repository root for the exact wording before you rely on it.

Dependency weight is light. package.json lists a single runtime dependency, three at ^0.185.0, and one dev dependency, vite at ^8.0.0. The version specifiers use the caret range, so a fresh npm install can pull a newer minor or patch release of either. Three.js has historically made breaking changes across minor versions, so a caret range on three is a real upgrade risk for a project whose rendering code reaches into materials and render targets directly.

Maintenance is the other cost. The last push was on 2026-07-05, and no releases were retrieved, so there is no tagged version to upgrade to. Upgrading means tracking the main branch. The scripts are dev, build and preview, and there is no test script in package.json, so there is no automated check that a Three.js bump has not broken the post-processing pipeline.

Editorial conclusion

Dungeon Forge is for people who want to read a working generation pipeline end to end, or to show a seeded dungeon rebuilding itself in a browser. It is not for teams that need a library they can import into an existing engine, because the generator and renderer share one module and one RNG stream. Before adopting it, open src/main.js and check whether the pipeline can be separated from the render loop, and confirm the MIT licence terms against how you intend to ship it.

Frequently asked questions

Is three.js still used?

Yes. Dungeon Forge depends on three at ^0.185.0 in package.json, and the README says the dungeon is rendered live with Three.js. The custom post-processing stack is written against Three.js render targets.

What is three JS used for?

In this project it draws the generated dungeon: instanced floor tiles, walls, props and decorations, plus a hand-written post-processing pipeline with bloom, blur, tilt-shift, colour grade, vignette and film grain. The README describes the whole scene as rendered live with Three.js.

Is there anything better than three JS?

The repository does not compare Three.js with other WebGL libraries, so there is no basis for a comparison here. What can be said is that Dungeon Forge depends on three alone, and that swapping the renderer would mean rewriting the instanced rendering and post-processing code in src/main.js.

Official sources

  1. Issues
  2. License: MIT
  3. majidmanzarpour/threejs-procedural-dungeon on GitHub
  4. README
Community notes

Community notes