This problem has been a really interesting one to work on. At the start I didn't think this would be possible with 'pure' Cycles nodes - without resorting to OSL - but was surprised to discover it is. I've certainly learned a lot along the way.
Here's the material :
(glare added in compositor)
And here's the node tree (click to enlarge) :
The pattern can be generated by measuring the distance of each point being sampled to each of a number of fixed reference points in a similar way to how the Voronoi texture is produced. By carefully positioning the reference points we can generate a hexagonal pattern.
Starting with a single reference point (held in a Combine XYZ node), the vector between the reference point and the texture coordinate can be calculated simply by subtracting one from the other using a Subtract Vector Math node. This is passed into both inputs of a Dot Product Vector Math node to generate a scalar distance (actually 'distance squared').
This structure can be replicated for multiple reference points and the results of each combined using a Minimum node. This will effectively return the distance (squared) to the closest reference point.
Greater Than nodes can then be used to compare each individual output with this combined 'Minimum'. This will produce 3 outputs that will be '0' if the corresponding reference point is the closest, otherwise '1'. These values are also passed through Subtract nodes to invert their output. We now have two sets of 'mask' outputs - one set that's 0 if the corresponding reference point is the closest, another that is '1' if the corresponding reference point is closest.
To be able to control the edges of the cells (rather than having a gradient emanating from the centre) we need to be able to detect the boundary between one cell and the next. The boundary occurs at the point where the distance to one cell equates to the distance to the next closest cell. This can be achieved by determining the minimum distance to all of the reference points excluding the one we already know to be closest. Subtracting the closest distance from the next closest will give a measure of the distance to the cell boundary - this will be zero at the boundary (where the distance to each reference is the same) and increase as we move further towards the centre of a cell. For the first reference point we can do this as follows :
Note the multiplication by the mask - this is to ensure that each value is only used when the point being measured is closest to the corresponding reference point - the output will be zero outside the corresponding cell.
Replicate a similar structure for each of the other reference points - in each case this will need to combine the outputs from all reference point distances of the other reference points excluding the one corresponding to the 'current' one - which we know will be the actual minimum if the mask will include that point - ie, the first combines 2 and 3, the second 1 and 3, the third 1 and 2. Since each of the resultant outputs are masked to zero when the sample is outside its cell we can simply combine them all as shown :
To be able to colour the individual cells we need to be able to determine the vector coordinates of the corresponding reference point. Again we can use the masks to pick out the relevant value for the closest reference and these can be simply combined to produce a single vector. In this case, the 'anti-mask' (set to 0 where that reference point is closest, otherwise 1) is most useful as it can be used in a Multiply Colour node to multiply the vector by zero when it is not the closest, otherwise allow the vector through unchanged.
For a hexagonal pattern we need to position the reference points in a grid representing the centres of the cells. By calculating only those reference points that are closest to the point being sampled we can re-use the above nodes to cover the whole texture space. This would technically be possible with only 3 reference points but becomes much simpler if we replicate the node structures to work with 5 cells at a time.
To position the cells, the 'grid' coordinates are determined by dividing the texture coordinate by the horizontal and vertical pitches (chosen as 1.5 and 0.866 to generate the correct spacing for regular hexagons) and rounded down to integers. Modulo 2 is used (which returns '0' for even rows and '1' for odd rows) to determine the Row Type and Column Type to allow alternating rows to shift across in the hexagonal pattern.
Once the location in the grid is known, the Generate Point Coordinates Frame calculates the locations of the "nearest" reference points. These are multiplied by the Horizontal and Vertical pitch to get coordinates that can be used with the current sample point to determine the distances. This can be illustrated as follows with the current sample point indicated in white with the 5 nearest cells shown :
The cell border can be adjusted via the Edge Offset and Edge Power values. Larger Offset results in thicker borders to the cells while the Power affects the hardness of the cell edge. Negative values can give some interesting effects (eg, Offset = -0.5 with Power = 1.0 provides a quilted effect with soft borders, while a small positive Offset and Power 0 gives hard narrow lines between cells).
For the cell colours, a noise texture is used to generate a value between 0 and 1 based on the cell vector and this is multiplied up and passed through a Modulo 1 node to generate a (mostly) linear distribution. An Offset is added to allow it to be animated and the result passed through a further Modulo 1 so that the value wraps around at the edges of the 0 to 1 range. This is then passed through a colour ramp to generate the final shade for each cell. Using the cell coordinate as a basis for this colour generation ensures each cell is coloured consistently.
The maths used to manipulate the grid and dynamically position the reference points works fine with positive coordinates - so plain old 'Generated' coordinates should work well. However, switching to Object coordinates will result in negative values which upset the calculations. To work around this you need to increase the Location of the Mapping node to avoid the negative texture coordinates.
Blend file attached.