Algoritmo WFC (Wave Function Collapse)


#1

Um showcase e explicação do WFC para geração procedural.

O algoritmo cria imagens (output) que são localmente parecidos com o exemplo dado (input).
Isso significa que para quaisquer segmentos NxN no output, há um segmento NxN igual no input. Todas as outras características emergem desse conceito inicial.

Funcionamento básico (transcrição do original):
  1. Read the input bitmap and count NxN patterns.
    (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 superpostion 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:

  • Observation:
    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).
    Collapse this element into a definite state according to its coefficients and the distribution of NxN patterns in the input.
  • Propagation: propagate information gained on the previous observation step.
  1. By now all the wave elements are either in a completely observed state (all the coefficients except one being zero) or in the contradictive state (all the coefficients being zero). In the first case return the output. In the second case finish the work without returning anything.

Exemplos de variações possíveis sobre o algoritmo:

  • Segmentos não NxN, mas NxM. Particularmente útil em casos onde há viés horizontal ou vertical, e para casos em que o input é muito pequeno. Se 3x3 é uma área muito grande do input e 2x2 é muito pequena, 2x3 ou 3x2 podem solucionar isso.
  • Os segmentos NxN obtidos do input também podem ser rotacionados e/ou espelhados antes de serem adicionados ao “dicionário” do algoritmo.
  • O algoritmo também funciona com coisas completamente diferentes, como volumes 3D, animações, áudio, texto, etc.

A seção “Notable ports, forks, and spinoffs” tem vários exemplos interessantes de uso, inclusive alguns extremamente não triviais. Deixo aqui imagens de alguns dos exemplos mais interessantes que achei no GutHub do autor ou na seção de spinoffs:

Galeria: