LayerProcGen: Contextual Generation (2024)

A central feature of the LayerProcGen framework is to support contextual generation without compromising determinism. Generative operations can deterministically cross chunk boundaries, making context-based operations possible. For example:

  • Distances between random points can be relaxed.
  • Data in 2D arrays can be subject to blurring or other kernel-based filters.
  • Pathfinding across chunk boundaries can be performed.

This is possible by dividing the generation into multiple layers and keeping a strict separation between the input and output of each layer.

Point relaxation in the infinite plane can be performed as follows. Consider a layer A and a layer B which have chunks of the same size.

  • A chunk of layer A - let's choose chunk A 5,5 - generates a set of initial random positions within the chunk bounds. Some of the positions may be undesirably close to each other.
  • In layer B chunk B 5,5 reads the initial random positions from chunk A 5,5 and its eight neighbor chunks.
  • Chunk B 5,5 then runs a point relaxation algorithm on the combined set of points from all nine chunks in layer A. This does not modify any of the original points stored in layer A. Rather, the adjusted points originating from chunk A 5,5 are stored in chunk B 5,5 and the adjusted points originating from the neighbor chunks are discarded, as they already served their purpose of affecting the relaxed points in B 5,5.

Since the relaxed points in Layer B do not modify the original unrelaxed points in Layer A, input and output is kept separated, and the process is deterministic.

As long as the radius of influence in the point relaxation algorithm is less than the width of a chunk, the result here is the same as it would have been if the relaxation algorithm was somehow run on all the points in the infinite plane at once.

Let's say we have a PatternLayer which provides pixels in the infinite plane. It can provide pixels within a given rectangle on demand based on a global deterministic pattern. We don't need to know the chunk size, as we can consider it an implementation detail.

We also have a BlurLayer which has chunks of size 100 x 100 pixels. It's responsible for calculating and storing a blurred version of the pattern with a blur radius of 20 pixels.

  • A BlurLayer chunk requests pixel data from PatternLayer corresponding to its own 100 x 100 pixels padded by 20 pixels in each direction, for a total of 140 x 140 pixels. These are stored in a temporary grid.
  • The BlurLayer chunk then runs a blur operation on its temporary 140 x 140 grid. This does not modify any of the original pixel data stored in PatternLayer.
  • The center 100 x 100 pixels of the temporary pixel grid are stored in the BlurLayer chunk and the temporary grid is then discarded.

Since the blurred pixels in BlurLayer do not modify the original sharp pixels in PatternLayer, input and output is kept separated, and the process is deterministic.

We'll now go over why the result here is the same as it would have been if the blur operation was somehow run on all the pixels in the infinite plane at once.

A blur operation can happen in one or multiple iterations. For example, if the blur kernel uses only the eight neighboring pixels (that is, a blur radius of one pixel), then the 20 pixels of padding would leave room for 20 blur iterations.

The most efficient way to do this is to calculate each iteration on only the pixels needed. For 20 iterations it would go like this:

  • Iteration 1 calculates blur for 138 x 138 pixels based on 140 x 140 pixels as input.
  • Iteration 2 calculates blur for 136 x 136 pixels based on 138 x 138 pixels as input.
  • ...
  • Iteration 20 calculates blur for 100 x 100 pixels based on 102 x 102 pixels as input.

Note that there are no edge conditions needed for how to handle blurring at edges of a grid, since the output in each step is smaller than the input. This ensures all output pixels are good and not tainted by lacking or incorrect data at the edges.

From the point of view of a third layer, the chunk size of BlurLayer can also be an implementation detail. BlurLayer can simply provide an API to request pixels within a given rectangle.

LayerProcGen: Contextual Generation (2024)

References

Top Articles
Latest Posts
Article information

Author: Van Hayes

Last Updated:

Views: 5979

Rating: 4.6 / 5 (66 voted)

Reviews: 89% of readers found this page helpful

Author information

Name: Van Hayes

Birthday: 1994-06-07

Address: 2004 Kling Rapid, New Destiny, MT 64658-2367

Phone: +512425013758

Job: National Farming Director

Hobby: Reading, Polo, Genealogy, amateur radio, Scouting, Stand-up comedy, Cryptography

Introduction: My name is Van Hayes, I am a thankful, friendly, smiling, calm, powerful, fine, enthusiastic person who loves writing and wants to share my knowledge and understanding with you.