Trying to implement an interesting procedural tiling pattern

I saw this image of a tiling pattern, and I started to wonder how I might approach something like this in a shader:

Some of the key details:

  • It’s composed of squares/rectangles with dimensions ranging from 1x1 to NxN, where N would ideally be adjustable.
  • It’s procedural, so it wouldn’t repeat over a large area.
  • Adjacent tiles would have a good chance to be a different color from each other, but not always. (The colors should just look random.)
  • A constant width edge should surround each tile.
  • This isn’t just a matter of subdividing a square into smaller squares, which would give the overall pattern a feel of being a regular grid with some smaller pieces. The whole thing feels kind of randomly put together.

I thought it would be fun to consider how I would approach something like this. I felt that a good place to start was to imagine a function into which I pass the UV coordinates, and it returns data about the rectangle to which that pixel belongs. It would return the (x,y) coordinates of the lower left corner, the height and with of the rectangle, and probably a noise output for the corner so I could assign a “random” color to the tile.

So then what would that kind of function look like? I decided maybe I should start by considering a 1D version of this, just a line broken up into random segments of lengths 1 through N.

8697084--1173768--upload_2023-1-1_15-17-50.png

The idea here would be, I’d pass in a single value (U), and get out the integer Start Position and Length of the line segment that U value falls into. So, if I passed in 5.25, for example, that falls within the purple line, so I’d get a value like “4” for the start position, and “3” for the length.

That’s about as far as I’ve gotten so far, because I can’t think up a good function for doing this sort of thing. It’s impractical to complete the complete series between 0 and U before deciding where U falls in the series. I’m basically trying to round down to the nearest integer in some magical series that has random gaps of distances ranging from 1 to N between each subsequence element in the series. I’m not aware of any efficient way of generating such a series.

Anyway, sometimes just writing up my thoughts helps to come up with an idea, but not yet in this case. But I figured there was a possibility that what I’m trying to do isn’t really possible/practical, and that someone would quickly realize that and advise me to give up. But for now I figure I’ll just keep thinking a bit about this and update this thread if I have a breakthrough.

Playing around with this, I’ve come up with a (pretty bad) approach at least to the 1D version. Here’s a solution where the wall is tiled in strips of random colors and widths:

The strips range from between 1 and 5 UV units in width. I won’t show the Shader Graph for this, because it’s a mess, and I honestly expect to throw this out and start over with a better approach. But the general approach involves

  • Compute a “MaxNearbyNoise” of the UV.x value.

  • Floor the UV.x value, pass that into a Noise function, to get a noise value.

  • Do the same thing with nearby floor(UV.x) values +1, +2, -1, and -2. Now we have a noise value for ourself and four neighbors.

  • Take the Max of those five values.

  • Compare this MaxNearbyNoise to the MaxNearbyNoise of floor(UV.x) - 1. If it’s different, then our current value is the start of a group. If it’s the same, then compare MaxNearbyNoise to MaxNearbyNoise of floor(UV.x) - 2, and so on, until we determine where the current group starts.

  • Do something similar by comparing MaxNearbyNoise to floor(UV.x) + 1 to determine how long this group goes on.

So then we know noise value associated with our current group, and whether we either start or end the group (or both, if the group is only 1 unit wide). With that, we can set a random color based on the group’s noise, and add borders if we’re either the start or the end.

This spreadsheet might give a better idea of what’s going on here, where Max Nearby Noise is just computing a local max of nearby noise values, and “Start of New Group” compares that index’s MaxNearbyNoise to the prior one.

Anyway, this is probably a garbage approach. It’s a lot of noise calculations per pixel, and that’s just for 1D. I don’t really know if I can extend this to 2D either…

I would maybe try solve the problem logically on a “papaer”.

How would you try to make something like that look randomised.

Personally I would start of with placing the biggest rectangular randomly.
Perhaps placing such in a spacial map would help.
Then need place smaller rectangular in empty spaces.

You can subdivide process toward s. Allesr rectangular, up to 1x1.

You maybe could even utilise equivalent of 2d array, texture, or flattened 1d array if needed to, to find empty spaces. Or checkout, if space is occupied.

In a process, it is multi pass procedure. Where generating each of rectangular dimension, is own pass. Starting with largest rectangular in a first pass.

Just thoughts.
Did you look up for mathematical algorithms? Such patterns ssurely has own mathematical name.

I did try to look up possible general approaches to this, but I wasn’t really sure what to even call this kind of tiling. It’s not really a subdivided tiling, so I’m not sure what I’d call it.

I’ve tried to design the algorithm on paper, and the approach you described seems like a good way for a human to try to tile a region with this kind of pattern. But for shader logic, which determines the value of a specific pixel rather than the design as a whole, I figure a completely different kind of solution is needed.But I did consider whether some stuff could be pre-computer and given to the shader, as kind of map it could use. I’m sure that’s possible, but then it would end up repeating at some point.

I’m mostly just looking at this shader for fun, and maybe I’ll come up with a clever solution at some point as I think of ideas and test them.

Yep, I see this to be more problematic for shader solution.

I do wonder, does other patterns work with shaders?
Or did you maybe try to look up into quad tree, or other spatial maps solution for shaders? May e that will give you some direction of thoughts?

Quadtree is interesting. I’ll give that some more thought. I think this tiling I’m trying for is probably more difficult than Quadtree, but maybe an iterative approach like that is a good place to start.

1 Like