WaveFunctionCollapse README

The project's README from github.com/mxgmn/WaveFunctionCollapse. As one markdown file: README.md.

WaveFunctionCollapse

This program generates bitmaps that are locally similar to the input bitmap.

main collage

main gif

Local similarity means that

In the examples a typical value of N is 3.

local similarity

WFC initializes output bitmap in a completely unobserved state, where each pixel value is in superposition of colors of the input bitmap (so if the input was black & white then the unobserved states are shown in different shades of grey). The coefficients in these superpositions are real numbers, not complex numbers, so it doesn't do the actual quantum mechanics, but it was inspired by QM. Then the program goes into the observation-propagation cycle:

On each step the number of non-zero coefficients decreases and in the end we have a completely observed state, the wave function has collapsed.

It may happen that during propagation all the coefficients for a certain pixel become zero. That means that the algorithm has run into a contradiction and can not continue. The problem of determining whether a certain bitmap allows other nontrivial bitmaps satisfying condition (C1) is NP-hard, so it's impossible to create a fast solution that always finishes. In practice, however, the algorithm runs into contradictions surprisingly rarely.

Wave Function Collapse algorithm has been implemented in C++, Python, Kotlin, Rust, Julia, Go, Haxe, Java, Clojure, Free Pascal, Dart, p5js, JavaScript and adapted to Unity, Unreal Engine 5, Godot 4 and Houdini. You can build WFC from source, download an official release for Windows, download an interactive graphical version from itch.io or run it in the browser. WFC generates levels in Bad North, Caves of Qud, Dead Static Drive, Townscaper, Matrix Awakens, several smaller games and many prototypes. It led to new research. For more related work, explanations, interactive demos, guides, tutorials and examples see the ports, forks and spinoffs section.

Watch a video demonstration of WFC algorithm on YouTube: https://youtu.be/DOQTr2Xmlz0

Algorithm

  1. Read the input bitmap and count NxN patterns.
    1. (optional) Augment pattern data with rotations and reflections.
  2. Create an array with the dimensions of the output (called "wave" in the source). Each element of this array represents a state of an NxN region in the output. A state of an NxN region is a superposition of NxN patterns of the input with boolean coefficients (so a state of a pixel in the output is a superposition of input colors with real coefficients). False coefficient means that the corresponding pattern is forbidden, true coefficient means that the corresponding pattern is not yet forbidden.
  3. Initialize the wave in the completely unobserved state, i.e. with all the boolean coefficients being true.
  4. Repeat the following steps:
    1. Observation:
      1. Find a wave element with the minimal nonzero entropy. If there is no such elements (if all elements have zero or undefined entropy) then break the cycle (4) and go to step (5).
      2. Collapse this element into a definite state according to its coefficients and the distribution of NxN patterns in the input.
    2. Propagation: propagate information gained on the previous observation step.
  5. By now all the wave elements are either in a completely observed state (all the coefficients except one being zero) or in the contradictory state (all the coefficients being zero). In the first case return the output. In the second case finish the work without returning anything.

Tilemap generation

The simplest nontrivial case of the algorithm is when NxN=1x2 (well, NxM). If we simplify it even further by storing not the probabilities of pairs of colors but the probabilities of colors themselves, we get what we call a "simple tiled model". The propagation phase in this model is just adjacency constraint propagation. It's convenient to initialize the simple tiled model with a list of tiles and their adjacency data (adjacency data can be viewed as a large set of very small samples) rather than a sample bitmap.

Lists of all the possible pairs of adjacent tiles in practical tilesets can be quite long, so I implemented a symmetry system for tiles to shorten the enumeration. In this system each tile should be assigned with its symmetry type.

symmetries

Note that the tiles have the same symmetry type as their assigned letters (or, in other words, actions of the dihedral group D4 are isomorphic for tiles and their corresponding letters). With this system it's enough to enumerate pairs of adjacent tiles only up to symmetry, which makes lists of adjacencies for tilesets with many symmetrical tiles (even the summer tileset, despite drawings not being symmetrical the system considers such tiles to be symmetrical) several times shorter.

knots tiled rooms circuit 1 circuit 2 circles castle summer 1 summer 2

Note that the unrestrained knot tileset (with all 5 tiles being allowed) is not interesting for WFC, because you can't run into a situation where you can't place a tile. We call tilesets with this property "easy". Without special heuristics easy tilesets don't produce interesting global arrangements, because correlations of tiles in easy tilesets quickly fall off with a distance. Many easy tilesets can be found on Guy Walker's website. Consider the "Dual" 2-edge tileset there. How can it generate knots (without t-junctions, not easy) while being easy? The answer is, it can only generate a narrow class of knots, it can't produce an arbitrary knot.

Note also that Circuit, Summer and Rooms tilesets are non-Wang. That is, their adjacency data cannot be induced from edge labels. For example, in Circuit two Corners cannot be adjacent, yet they can be connected with a Connection tile, and diagonal tracks cannot change direction.

Higher dimensions

WFC algorithm in higher dimensions works completely the same way as in dimension 2, though performance becomes an issue. These voxel models were generated with N=2 overlapping tiled model using 5x5x5 and 5x5x2 blocks and additional heuristics (height, density, curvature, ...).

voxels

Higher resolution screenshots: 1, 2, 3.

MarkovJunior repository contains an implementation of the 3d simple tiled model with many tilesets and examples.

Constrained synthesis

WFC algorithm supports constraints. Therefore, it can be easily combined with other generative algorithms or with manual creation.

Here is WFC autocompleting a level started by a human:

ConvChain algorithm satisfies the strong version of the condition (C2): the limit distribution of NxN patterns in the outputs it is producing is exactly the same as the distributions of patterns in the input. However, ConvChain doesn't satisfy (C1): it often produces noticeable defects. It makes sense to run ConvChain first to get a well-sampled configuration and then run WFC to correct local defects. This is similar to a common strategy in optimization: first run a Monte-Carlo method to find a point close to a global optimum and then run a gradient descent from that point for greater accuracy.

P. F. Harrison's texture synthesis algorithm is significantly faster than WFC, but it has trouble with long correlations (for example, it's difficult for this algorithm to synthesize brick wall textures with correctly aligned bricks). But this is exactly where WFC shines, and Harrison's algorithm supports constraints. It makes sense first to generate a perfect brick wall blueprint with WFC and then run a constrained texture synthesis algorithm on that blueprint.

Comments

Why the minimal entropy heuristic? I noticed that when humans draw something they often follow the minimal entropy heuristic themselves. That's why the algorithm is so enjoyable to watch.

The overlapping model relates to the simple tiled model the same way higher order Markov chains relate to order one Markov chains.

WFC's propagation phase is very similar to the loopy belief propagation algorithm. In fact, I first programmed belief propagation, but then switched to constraint propagation with a saved stationary distribution, because BP is significantly slower without a massive parallelization (on a CPU) and didn't produce significantly better results in my problems.

Note that the "Simple Knot" and "Trick Knot" samples have 3 colors, not 2.

One of the dimensions can be time. In particular, d-dimensional WFC captures the behaviour of any (d-1)-dimensional cellular automata.

Used work

  1. Alexei A. Efros and Thomas K. Leung, Texture Synthesis by Non-parametric Sampling, 1999. WaveFunctionCollapse is a texture synthesis algorithm. Compared to the earlier texture synthesis algorithms, WFC guarantees that the output contains only those NxN patterns that are present in the input. This makes WFC perfect for level generation in games and pixel art, and less suited for large full-color textures.
  2. Paul C. Merrell, Model Synthesis, 2009. Merrell derives adjacency constraints between tiles from an example model and generates a new larger model with the AC-3 algorithm. We generalize his approach to work with NxN overlapping patterns of tiles instead of individual tiles. This allows to use a single image as the input to the algorithm. By varying N, we can make the output look more like the input or less. We introduce the lowest entropy heuristic that removes the directional bias in generated results, is defined for irregular grids and is better suited for pre-constrained problems. We implement a tile symmetry system to reduce the sizes of inputs. We visualize partially observed states, either with color averaging or per-voxel voting. Merrell also introduced a method of incrementally modifying the model in parts to reduce the failure rate (which we don't use here). Recently the author created a page for model synthesis and published code.
  3. Alan K. Mackworth, Consistency in Networks of Relations, 1977. WFC translates a texture synthesis problem into a constraint satisfaction problem. Currently it uses the AC-4 algorithm by Roger Mohr and Thomas C. Henderson, 1986.
  4. Paul F. Harrison, Image Texture Tools, 2005. WFC was also influenced by the declarative texture synthesis chapter of Paul Harrison's dissertation. The author defines adjacency data of tiles by labeling their borders and uses backtracking search to fill the tilemap. A demonstration of the algorithm is available on the web.

How to build

WFC is a console application that depends only on the standard library. Get .NET Core for Windows, Linux or macOS and run

dotnet run --configuration Release WaveFunctionCollapse.csproj

To build the application without running it, run

dotnet publish --configuration Release WaveFunctionCollapse.csproj

After this, a self-contained app will appear in the bin/publish folder. Run WaveFunctionCollapse.exe - generated artifacts will appear in the output folder. Edit samples.xml to change model parameters.

Alternatively, use build instructions from the community for various platforms from the relevant issue. Casey Marshall made a pull request that makes using the program with the command line more convenient and includes snap packaging.

Notable ports, forks and spinoffs

Credits

Circles tileset is taken from Mario Klingemann. FloorPlan tileset is taken from Lingdong Huang. Summer tiles were drawn by Hermann Hillmann. Cat overlapping sample is taken from the Nyan Cat video, Water + Forest + Mountains samples are taken from Ultima IV, 3Bricks sample is taken from Dungeon Crawl Stone Soup, Qud sample was made by Brian Bucklew, MagicOffice + Spirals samples - by rid5x, ColoredCity + Link + Link 2 + Mazelike + RedDot + SmileCity samples - by Arvi Teikari, Wall sample - by Arcaniax, NotKnot + Sand + Wrinkles samples - by Krystian Samp, Circle sample - by Noah Buddy. The rest of the examples and tilesets were made by me. Idea of generating integrated circuits was suggested to me by Moonasaur and their style was taken from Zachtronics' Ruckingenur II. Voxel models were rendered in MagicaVoxel.

second collage

voxel perspective

WaveFunctionCollapse (mxgmn/WaveFunctionCollapse)

Searching Database…

这是什么?一个用 C# 编写的程序,它以你提供的一张示例图片为参照,在本地生成与之局部相似的位图和瓦片地图,其思路借鉴了量子力学。
'局部相似于输入'到底是什么意思?输出中只会包含输入图片里存在的 NxN 像素图案(通常是 3x3),并且每种图案出现的频率应与它在示例中大致相同——也就是说,绝不会出现任何新的东西。
我怎么把它跑起来?在 Windows、Linux 或 macOS 上安装 .NET Core 并运行本项目;构建后会在 bin/publish 生成一个自包含的应用,运行 WaveFunctionCollapse.exe 就会把结果写入 output 文件夹。想改参数就编辑 samples.xml。
除了 .NET 之外还需要装别的东西吗?不用。这个程序只依赖标准库,所以 .NET Core 就是全部的前置要求。
它总能生成出一张图吗?有时会遇到矛盾——某个像素的所有选项都被排除了,这时它会直接停止,什么也不返回。这个问题的通用形式是 NP 难的,所以没有既快又保证能算完的解法——不过实际上失败的情况出奇地少见。
我实际能用它来做什么?主要用于游戏中的关卡生成和像素画,这些场景看重'只会出现输入里的图案'这一硬性保证;它不太适合生成大幅的全彩纹理。
它只能在 Windows 上跑,还是其他系统也行?不限于 Windows:你可以在 Windows、Linux 或 macOS 上从源码构建,下载官方 Windows 发行版,从 itch.io 获取带图形界面的交互版本,也可以直接在浏览器里运行。
量子力学那部分到底是怎么工作的?输出的每个区域一开始都处于输入图案的叠加态。算法反复找出香农熵最低的区域,把它坍缩成一个确定的状态,并把结果传播开来,直到整张图都被'观测'完毕。
它只能靠示例图片来工作,还是我也可以自己定义瓦片规则?有一个简单的 tiled model,它接受瓦片列表加上邻接关系数据,而不需要示例位图;另外还有一套对称性机制,能让含对称瓦片的 tileset 的邻接列表保持简短。
它能生成 3D 内容吗?能。这个算法在更高维度上以同样的方式工作——README 里展示了用 N=2 的 overlapping 模型生成的体素模型——不过性能会成问题。MarkovJunior 仓库里还有一个带多套 tileset 的 3D tiled model。
有哪些真正的游戏在用它?WFC 在 Bad North、Caves of Qud、Dead Static Drive、Townscaper 和 Matrix Awakens 中生成关卡,此外还有几款较小的游戏和大量原型作品在用,它还催生了新的研究。
Creator
mxgmn
Size
30.4 MB
Stars
25.4K
Age
10y
Commits · 90 Days