Blog

One way to generate noise like that is to add various layers of Perlin noise or smooth noise together, where each layer is more blurry than the next. You can get more details on the case for square grids in this article: How to use Perlin noise in your games.

That article also lists many uses of that type of noise in games. Among other things, it’s useful for generating things such as clouds, maps, and terrain. It’s also useful to simulate certain textures such as marble or wood. You can also use it to place items (such as certain types of building in cities). We used it in Game 16 to drive light colors, giving the maze some visual variety, but still keeping some coherence.

In this article, I will show you a quick-and-dirty way to implement that type of noise on a hex grid. I take a very informal approach which is suitable for the use in games.

Noise generation can become very technical, and in applications where subtle differences matter, a more mathematically rigorous approach is appropriate.

It’s easier to understand the algorithm when it is broken up like it is in this article. Unfortunately, this makes the algorithm quite slow. It’s possible to improve the performance drastically if the steps are re-arranged slightly, if some steps are done in-place, and if other tricks are used to avoid multiple iterations.

Although this tutorial uses some functions that are provided by our Grids library, you should be able to convert the concepts to any hex library.

The basic idea is simple:

Generate white noise at various resolutions (but in the same sized grid).

Blur the layers (more blurring is required for lower resolutions).

Add them together.

Generating white noise at the highest resolution is easy: simply assign a random value to each cell in the grid.

For lower resolutions, it becomes a bit trickier. In the case of square grids, we can sample at a half the resolution by this scheme:

C#

1

sampledNoise[x,y]=noise[x/2,y/2]//Note: I mean floor division, and this is not Grids notation!

We want something similar for hex grids. Although the scheme above will also work for hex grids, it give us parallelogram-shaped patches. What we would really like is hexagonal patches. This is possible, but a bit tricky to understand.

This assigns to each point a number 0 to 6 that we will call the remainder index of the point.

We then note that every point can be written in the form:

\(p = au + bv + r\)

for some \(a\) and \(b\) , where \(u = [7, 0] \) and \(v = [2, 1] \) are the sides of the unit parallelogram (one of the smallest parallelograms that repeats in the pattern) , and \(r\) is one of the points in a hex-shaped patched of 7 hexes at the origin:

C#

1

2

3

4

5

6

7

[0,-1]

[1,-1]

[-1,0]

[0,0]

[1,0]

[-1,1]

[0,1]

All we need to do is solve for a and b, and then use the point [a, b] as the point to sample. You will see this roughly resembles integer division (from there the terminology used in the code). I do not show how the solution is derived here – it’s a lot of math!

C#

1

2

3

4

5

6

7

8

9

10

11

12

publicPointyHexPoint Div2(PointyHexPoint point)

{

intremainderIndex=point.GetColor3_7();

varevenPoint=point-Remainders[remainderIndex];

vara=evenPoint.Y;

varb=Mathi.Div(evenPoint.X-2*a,7);

a=a+3*b;

b=-b;

returnnewPointyHexPoint(a,b);

}

Here, the Remainders is a list of the 7 points above, sorted by their remainder indices (thus not in the order given above).

When we fill points in one grid, sampled at these “divided” points in a noise grid, the effect is as this below:

By re-applying the function to the point before we sample, we get even lower resolutions of noise.

The next step is to blur these. We will use a hexagonal-box blur for this step. The area of our patches grow by a factor of 7 in each iteration:

The final step is to scale these together and add them up. We scale the highest resolution by 1, the second by 2, the third by 4, and the fourth by 8. We add then together, and divide by 15 to normalize values between 0 and 1.

Once we have the noise, we can use it to drive the various things described earlier. In the image below, we generated three noise sets. Two is used to blend between two colors each; the third is used to blend the images together.

You can also use the noise to drive tile selection, as shown in the images below: