# How to create a patterned object with variable pattern density in real-time?

Assume there is some value p, calculated per-frame, that varies continuously over the surface of an object. The value of p determines the density of some pattern on the surface. For example, in a case with only two possible densities if p < 0.3 it is high density, otherwise it is low.

I've thought of a simple high-level solution: create two textures, each of different densities, and based on the value of p sample from the appropriate one. However, there's a problem with the boundary between high- and low-densities.

Here is an example to illustrate the problem (note my problem is NOT exclusive to this example pattern of dots. I describe the patterns I'm working with later on):

And here is the threshold between low- and high- (displayed on the high density texture but that's not relevant.) If under the line, it implies the high-density texture should be sampled.

And finally here is the comparison between what is desired and what would actually happen using this method:

The problem is that when a high-density-only circle crosses the line, it will be ignored when p indicates the low-density texture to be sampled, resulting in a truncated circle. I don't know how to solve this problem because p varies every frame, so I can't just 'bake' a boundary between the two densities. It's easy to prevent the reverse problem by creating the high-density texture from the lower one (i.e. if a circle is on the low-density texture ensure it is on the high-density texture.)

I'm interested if anyone has a way to improve my solution or even has another method entirely. The constraint here is that p is calculated per-frame in real-time. Another constraint is related to the pattern texture: the pattern is black and white, where black is the pattern and white is the background (like the circles in the example). The pattern may not just be identical shapes repeated, but any arrangement of arbitrary black shapes over a white background. (Maybe pattern is the wrong choice of word.)

I'm not familiar with the research in this field so I wasn't sure which keywords to search, so I'd even appreciate if anyone could point me in the right direction.

• Is your actual texture also just black dots on white? If so, you might be able to generate the texture procedurally, e.g. with Poisson disc sampling with varying radii. Otherwise, if your texture is actually something more continuous, blending might be an option (that wouldn't work well for crisp textures like your example though). So if you could clarify what your actual pattern/texture looks like that might help getting more helpful answers. Jan 26 '16 at 7:37
• Post process? Something like a variant on edge detection: write out the distance to the nearest dot center then, in screen space, search each pixel's dot sized neighborhood for any (close to) zero values. This gives screen space dots, so you'd have to write and mess with UV derivatives to get back to texture space... Note that you still have a continuity problem - as the p high/low boundary moves across the surface, dots appear and disappear. If p can be continuous (a soft boundary) you might be able to shrink/grow the dots along the boundary... Jan 26 '16 at 16:50
• Another option is to look into Wang tiling. introduction, tile genetics, GPU gems Jan 27 '16 at 2:06
• Have you looked at texture bombing? http.developer.nvidia.com/GPUGems/gpugems_ch20.html Jan 27 '16 at 8:24
• Can you give an idea of the range of shapes/patterns you need to cover and how much flexibility there can be in the approach? @DanielMGessel's suggestion of changing the circle radii instead of their density might make things simpler and give smoother animation but it's not yet clear how much your approach is constrained. Jan 29 '16 at 12:19

In order to ensure that the pattern shapes are always either wholly present or absent, never cut off, it's necessary to ensure that the same p value is used for all texels within the shape. In your example of circles, all the texels in a given circle need to agree on p.

I assume that you have some way of evaluating p at a given point on the surface (whether it is looked up from a texture or calculated from some function). Then one way to ensure a group of texels all get the same p value is to ensure they all look it up from the same point.

The UVs of this evaluation point could be stored in extra channels of the pattern texture. For instance, you could have the red and green channels store the UV coordinates at which to evaluate p, the blue channel store the threshold at which to turn on that pattern element, and the alpha store the antialiased gray level of the pattern to display. The UV+threshold data could also be in a separate, secondary texture if desired.

To generate this UV+threshold texture, starting from an input pattern texture, you could programmatically find connected components (e.g. by searching for black pixels and flood-filling). Set the evaluation point for all texels in each component to the UV of the component's center, and generate a random threshold for it. Then, when rendering, use a pixel shader that first samples this texture, then looks up p at the given evaluation point and compares it to the given threshold.

That way, each pattern shape will see a uniform p value and threshold, and will either turn on or turn off fully. As p increases, more of the shapes will pass their threshold and appear, giving the impression of a continuously varying density.

• I really like this idea, I'll have to try it out. It makes perfect sense. Thanks!
– Ryan
Mar 12 '16 at 2:49

Another thought is along these lines. If you have a uniform point set defined on the plane and a mapping function from the plane to the target surface then the density function on the surface is how areas map from the plane surface to the target. So an area preserving map would result in a uniform points on the target.