The next step was to show how speckle patterns could create actual cell structure, where each cell was carefully delineated so that its edge could be accurately discerned and could also form the border to the neighboring cells. These are called Voronoi tessellations. You can see them in the diagram above. This comes from the discipline of computational geometry.
I also discussed spanning trees, the interconnection of speckle points to make interesting branching patterns. It is technique borrowed from the discipline of graph theory.
To the right you can see the frequency domain magnitude plot of the knit-structure texture that I create here. In the frequency domain, features near the center make up the large features of the image. A directionality to the texture corresponds to a directionality in the frequency domain, but rotated 90 degrees.
I specialize in synthesis.
Crossfades
The first tool I had to create was, for me, the capability to render into a Voronoi tessellation from another texture. And to do it so that the cell walls are invisible. This took some thought, and involves crossfades.
When trying to get non-tiling textures to mesh, one of the not-so-successful techniques is to create a rectangular crossfade.

The crossfade regions are rectangles that line the border of your non-tiling texture. The first thing is to fade them back. This means multiplying them by tapering functions. These tapering functions are 1 on the insides of the tile, and 0 at the edges.
Then, take the right crossfade region, and add it into the left crossfade region. This is like applying a soft mask. This assures that the right edge of the tile will mesh with the left edge.
Similarly, take the bottom crossfade region and add it into the top crossfade region.
Note: if you use a linear or a smoothstep tapering function, the general levels of the texture are preserved. The actual preservation of the levels is accomplished by any tapering function opacity = f(x) such that f(x) + f(1-x) = 1.
Once you have moved the crossfade regions over, you must them trim the texture down so it doesn't include the right and bottom crossfade regions. And your texture now tiles seamlessly.

The second most commonly-used tapering function is the smoothstep function. It is defined as shown by a simple cubic function. This one has the advantage of having a zero slope at either end of the taper, and so is less visible.
A linear function can leave a visible mach band at each end of the taper. Note also that, at the corners where the tapering functions overlap, we usually just multiply them. This makes trouble for the linear tapering function, though. So sometimes the tapering functions are combined using other means at the overlap.
OK, so now we understand rectangular crossfades. If it's so good, then why don't I use it? Because it's not good, that's why! There are several big drawbacks of this technique. Here are the worst three:
- eyes can see rectangular repeats very easily.
- features don't line up usually.
- the crossfaded region has a smoother texture than the rest of the pattern.
Features do not line up at the flaw edges of the texture, and this is the primary reason we can even see the flaw. Remember, if we use the texture as a paper grain in Painter, that the flaw will be magnified and made even more visible since the paper grain is quite visible in the brush stroke. Once we apply a crossfade to this texture, we should get a clean meshing of edges. At least, there should not be any visible horizontal and vertical edges.
But, after applying a 32-pixel crossfade, which should be large enough to prevent the unnecessary clipping of a 16-20 pixel feature, we can see (below the original) that there is a texture difference at the seams.
Such seams are made even more visible because of the rectangular repeat of the tile.
To combat this, we need to examine the actual instruments we use to judge the texture: our eyes.
The photoreceptor cells in the back of our eyes are arranged in a pattern that avoids obvious patterns. If we arrange cells of a texture in a similar way, the repeating pattern may be hidden.
So, conceptually, we replace the rectangular tile with tiles of various cellular shapes: we use the Voronoi tessellation to define the crossfaded cells, and the cells are in turn based on the speckle pattern which defies regularity so well.
Voronoi Tessellation Crossfade Mask Sets

The region straddles the edge of the cell, and intrudes into the neighboring cells by the half-width. Each neighboring cell has a corresponding crossfade region, that overlaps with this one. Because the crossfade regions straddle the edge of the cell, a cell's crossfade region actually dovetails with the neighboring cells' crossfade regions.

I create edge functions at each edge that are defined to be 1 at the inner edge and 0 at the outer edge. These functions are clamped to never go beyond the range [0...1]. Then I simply take the minimum value over all the edge functions for all edges of the cell.
But there is one more thing to do to make the cell masks correct: they must be normalized.
Our objective is to simply add up all the masks to produce a clean value of 1 for every pixel of the image. This should work perfectly within the cells, and also along the edges. This is because I have arranged for the edges to be a tapering function. But at the corners where three cells meet, these values will not sum to 1.
So we normalize the arrangement, and this assures us that the entire set of cell masks over the entire tessellation will add up to 1 at every pixel.
Assembling a New Texture Using the Crossfade Mask Set
This part is easy. For each cell, choose a swatch from the source texture, mask it by the cell mask, and add all the masked swatches, within each cell, into the new texture. This produces the new texture.
A straight addition produces a particular look. To get other looks, I decided on using a z-buffer approach. Here the swatch of source texture is multiplied by the mask (as in the additive approach) but instead of adding in each mask, we take the maximum value at the pixel of all the masked swatch pixels that land on the pixel. This actually can have the effect of changing the apparent edge of the cell.
To right is one such created texture. For this one, I chose an 80-point speckle and a 20-pixel crossfade. I used z-buffering to merge the cells, and this shows the effect of edge straddle on the result: the softness actually provides the zone of wiggle-room for the apparent edge of the cell.
The source texture is a highly softened result filtered by the FFT using a small 20-pixel ring.
It might not be apparent, but this is the same 80-point speckle that was used for the last example, but with a different crossfade and also a different edge function.
This result looks like bubbles on a surface and this is a result of using the same source swatch in every cell.
We can also use a different source swatch for each cell, as an option. This is more along the line of actual slice-and-dice, since it's really more of a jumble. But remember, with a random choice it's possible to choose the same swatch twice.
This shows the effect of random swatch choice and placement within the same 80-point speckle with a 20-pixel crossfade. Some glimmers of the same source texture swatch can be seen.
In this example, the additive technique was used for combining the cells, with edge straddle.
This method is useful for creating messy rock field textures and other strewn results.
Of course, the ultimate kind of slice and dice work comes from using a recognizable image as the source swatch and making sure it gets used for all cells. Such an example is shows at the end: an eye, complete with iris, pupil, and specular shine. And, of course, a bit of eyelid!
There's nothing that say texture can't work in color, but for now it is a grayscale application designed for the production of paper textures and grains.
Watching Fourier phase change in an image is endlessly fascinating.
The next part of the Texture series will complete the investigation into crossfade sets and show how you can use this technique to create cross-hatchings.
Then, we will concentrate on the more typical image processing operations that help us do things like anneal the image: operating directly on a texture.
Here's looking at you!
No comments:
Post a Comment