How can I create a hexagonal structure with Geometry Nodes?

I am looking for the simplest possible solution to create a hexagonal structure like this with Geometry Nodes:

Which solutions are there?

Additionally I want the hexagons to have different sizes and be extruded with different heights.

Furthermore, I want the top faces to have a different material than the sides.

I now had to change the title from "What is the easiest way to create a hexagonal structure with Geometry Nodes?" to "How can I create a hexagonal structure with Geometry Nodes?" due to the many interesting answers.

Temporary comment: I have guessed that with such a question some interesting answers should come, but this variety of good ideas and approaches (within 12 hours!) I really did not expect. My thanks and respect go to all the enthusiasts and Blender experts who have taken on this task here, and also otherwise so actively and helpfully enrich this Q&A platform day after day with their wonderful, grandiose and borderline brilliant solutions and help each other with tricky questions/answers and inspire others! ...the only problem I have left here is to mark one of these great answers as "Accepted Answer", because every way described here shows the wonderful diversity of Geometry Nodes in its own way. So sometimes I find it fundamentally hard not to dismiss a GN question as "opinion based". Anyway, I'm pretty sure that for many others, once again a question has been answered, as well as some new questions have been opened. This way we all learn something new every day. Thanks to all!

• i really like your question, but it is also a bit opinioned based...i think. The question is: what is the easiest? with the least nodes used? or the one which is easiest to understand? and even that is subjective...so maybe (i would just suggest) delete this one here : "Which way is the easiest/fastest/leanest?" so that people won't close your question because of "opinioed based" ...would be a pity May 19 at 11:30
• @Chris As always from your side: a good point! May 19 at 11:35
• Isn't even close to a true answer as it has pentagons (not to mention the shape), but a subdivided icosphere passed to dual-mesh is ALMOST a sphere made of tesselated hexagons. Close enough to be fun to play with if you want something hexish fast. There's pentagons at the 5-poles though, which the icosphere has a few of.
– Ben
May 19 at 15:54
• This tuotrial talks a good deal about how building hex meshs, convering the second half of your first bonus as well as your second bonus. May 19 at 18:23

Variant 1

Briefly summarized I proceed as follows:

1. First I create two lines with the node Mesh Line, which have as subdivision the triple of the given radius of a hexagon. One of the two lines I use as offset for the hexagonal structure.

Since a hexagon can be divided into six equilateral triangles, I calculate the height of such a triangle with the formula $$h={\frac {\sqrt {3}}{2}}\cdot r$$, which serves me as Y offset for one of the two lines. As X offset I use the radius of the hexagon, which is a side length of this triangle, and which I multiply by $$1.5$$.

2. To get the required grid, I instantiate this geometry along a line that runs along the Y axis. This line is divided with the previously calculated height of the triangle.

3. I then use the node Mesh to Points to convert the lines into points. Thereby I set a random value for the radius, which later serves me as a scaling on the X/Y-plane.

4. In the last step I instantiate the hexagons at these points and scale the instances with a random value for the Z-axis and the previously created radius of the individual points for the X/Y-axis.

I then only need to extrude these instances created in this way with the node Extrude and the mesh is ready. When extruding, I additionally capture the upper faces and assign another material to them with the node Set Material.

Variant 2

Another slightly modified method is to use a grid instead of multiple lines to create the necessary points.

Here every second row gets a different offset, which is also based on the calculation of the height of the equilateral triangle.

The rest of the procedure is otherwise identical to the first variant.

Both variants presented here can be found in the blend file:

I think this one might be the simplest:

both in terms of node count, and in ease of explanation:

1. Create a hex grid.
2. Populate it with Cylinders with Vertices set to 6 to make them hex shaped.
3. Assign a random value to the Cylinder Scale.

You need a combine XYZ node that only randomizes X and Y if you want the cylinders all on the same base height.

I think that joining two grids that are offset is a bit of a cheat, but it does give you a good hex pattern; and all of this in just six nodes. (7 if you want the cylinder bases at the same height.)

To answer a question in the comments, here's how to parameterize the grid size. Note that this version has the change to support the cylinders all sharing a base height as well.

Also note that this group would support the ability to color the sides and tops differently if you added these nodes:

Thanks to Markus von Broady for the comment correcting my material handling.

• I have to admit, in terms of the number of nodes, I love this solution the most! I would think that most users would want and expect exactly this simplicity from Geometry Nodes. However, I wonder how you could make the transformation flexible here. How exactly do you come up with 0.122 and how could that remain procedural? May 19 at 22:09
• And what I find really cool is that you offset the entire grid here! The only disadvantage would be that the numbering would no longer be continuous, but that is ultimately a question of application. May 19 at 22:18
• @quellenform The grid spacing requires that X and Y size are identical and that the X and Y offsets be .122 times that size, so a single Value input feeding both X and Y Size of the grid and feeding a math node that multiplies by .122 and then goes to a combineXYZ that sets both X and Y to that value while leaving Z 0 would make it procedural. May 19 at 22:54
• Also, .122 was arrived at by remembering that what we do with Blender is create illusions, so I eyeballed the offsets until they worked. (You can derive it mathematically, but I'm too lazy.) May 19 at 22:59
• This is pretty much the same as a shader answer from 2 years ago! Of course it's the way to go. Dooooooh! :) Drinks on you at the 19th. May 20 at 17:06

Here is a slight variation on this theme. In my example I create a mesh line in Y direction, with an offset of sqrt(3) * radius between points.

On this line I instance a mesh line in X direction, with an offset of 1.5 * radius between the points. Then I move every odd point by sqrt(3)/2 * radius in Y direction.

The grid of zig zag lines is then used to instance cylinders with 6 vertices and the given radius on each point. After instancing it is of course possible to randomize scale of each instanced cylinder etc. but I didn't implement that just yet, this is only doing the base structure.

Result with input attributes on the Geometry Nodes modifier:

The GN nodetree:

And the file:

• Thank you for this solution! Short and sweet! May 19 at 16:49

Crikey.. playing node golf with you guys, I'm not going to make the cut. :(

Mine was the grid approach, too..

..only difference, (after setting it to dimensions adapted from input) was using its points with a checker select:

and trying to make a more-or-less reusable group from it, which is then used outside, in a second modifier, to reach @quellenform's specs:

• I love to play node golf with you ;-) May 19 at 16:38

Using a plane which is subdivided and triangulated and then fed through dual mesh produces something which is close, but not quite as neat. You'd need to clip off the excess sides, but I was surprised by how close this got and how simple the node tree was:

However, if you then add nodes to separate out the hexagons and position them appropriately, you can rapidly get something very useful, with the benefit that none of it requires ANY complex maths. There's a magic number in there which should probably be based on the size of the model instead, but in general if you don't want to be calculating anything and just doing it by eye this approach might be a good one to take.

Blend File

(Unsure why this blend file is reported as not a blend by the typical upload locations. Tried both, didn't work)

• I really like this one. I knew there would be a dual somewhere, and couldn't find it! Is it easier to break your shear into a rotation followed by a scale? See here for a possibility... May 19 at 17:17
• @RobinBetts yes that's probably a much better way of doing things. It requires actual maths though, rather than -0.5 and 1.875 and I found those numbers by just changing the boxes in incrementally small amounts :)
– Ben
May 19 at 17:23
• After your update, I can now see what you meant. Well done, I like the approach that solves this without any math, I like it! May 19 at 17:40

Given an assumption of an even number of rows (could be fixed by deleting the last row of vertices at one point), I came up with this setup:

The Vector Curves node combines a color ramp functionality controlling how likely the cylinders are to touch (with unaltered noise they never touched, though forcing them to made them unhappy), and a map range node controlling the maximum cylinder height.

Keep in mind you don't actually need two materials to control the top, you could control the distinction inside the shader, thanks to which the renderer wouldn't need to duplicate vertices on material edges...

• Magic numbers legend: 1.732 - sqrt(3). 5.236 and 0.524 - as in the node title, it's radians(60*5) and radians(30) - the times 5 multiplier is the reciprocal of the snap value .2, which was taken arbitrarily (should probably be 1/6) May 20 at 0:09
• I decided not to control the distinction inside the shader, because that means by shaders only have 4 nodes between the two of them and I don't have to worry about someone rotating the whole thing. Maybe that was too simple? May 20 at 0:21
• @MartyFouts I also don't separate the top from the sides in the shader because OP asked for separate materials, but in my case since those are instances, the local Z of the instance remains unchanged and therefore you can easily distinguish the top by normal. May 20 at 0:25