Normal (Gaussian) Distribution Node

Imagine you are making a geometry nodes setup for generating crowds of people. Every person is different. Some are tall, some are short, and most are somewhere in between. So how do you decide on the height of each person? One approach would be to use a “Random Value” node centered on 1.75 meters. That means setting a minimum of 1.5 meters (shortest possible) and a maximum of 2 meters (tallest possible). Here’s what that would look like, except it is a 100*100 grid with a random distribution on the z-axis:

As you might have guessed, this isn’t a realistic result. In reality, there are people who are outside our height range. Also, in real life there are more average height people than very tall or very short people.

Another approach might be to use a noise texture. This is a better choice, since it will generate more average height people than very tall or very short people. Still though, there is an arbitrary minimum and a maximum height for people, which isn’t realistic:

What we need is a “Normal Distribution Node”. Rather than generating an even distribution of random values between two numbers, we could just provide it a mean value and a standard distribution. I made one, and here’s the result:

The random samples are generated using the “Box-Müller Transform”, which takes two random uniformly numbers distributed numbers and outputs a pair of normally distributed numbers. I learned how to make it work from this YouTube video. Here’s what the nodes look like:

Probably, there’s a lot of room for improvement, but it gives me the results I want. I’d like to know what you think! Maybe you have some ideas?

CORRECTION: The “Standard Distribution” node should be renamed to “Normal/Gaussian Distribution”.

EDIT: The original node setup I posted had multiple issues (now fixed, hopefully). I should have waited before posting it so I could have worked out the details. I’ve updated the screenshot of the node setup. There’s still one mystery for me. It seems I need to multiply the input standard deviation by about 0.62 to get the correct standard deviation (at least according to the “Attribute Statistic” node). Here’s the .blend file:

NormalDistNode.blend (936.0 KB)

1 Like

I took a look at your node setup. The Box-Muller transformation you are using (see eg. https://www.baeldung.com/cs/uniform-to-normal-distribution) takes two uniformly distributed random values u1 and u2 and returns two normally distributed values n1 and n2. A we only need one result, you can just always choose either n1 or n2, i.e., there’s no need to mix the values as you did. However, n1 and n2 both seem to have double STD so just divide the value by 2.

Here is a screenshot on how I modified your setup. Things marked in red can be removed.

I was actually looking for how to do similar with Shader nodes on spawned objects. Object info node can only produce one random value per instance, so I guess I’ll have to keep on looking.

Anyways, nice setup. Thanks for sharing! I really liked how you validated your node group with Attribute Statistic!

Hey @11kaks thanks for the ideas!

there’s no need to mix the values as you did.

Yes! Thanks for pointing that out. That’s why I was getting that problem where I needed to multiply the result by 0.62 to get the correct value. I thought I had the “Random Value” node set to give a random boolean, but it was returning a random float. That’s why the values were getting mixed and affecting the result.

However, n1 and n2 both seem to have double STD so just divide the value by 2.

I spent some time trying to figure out why this is happening. After going over the article you linked and compared the formulas for the Box-Muller transform, I realized I had forgotten to take the square root of -2*ln(u1). Fixing this seems to fix the problem of giving double the correct standard deviation.

The reason I was trying to choose from n1 and n2 at random is that I wasn’t sure if you could just return n1 or n2 and get a result that’s statistically accurate. However, I’ve recently learned the two normally distributed values (n1 and n2) are independent of each other. There’s no need to choose one at random. As you point out, you can just always return n1 or n2 (or I guess you could modify the output from the node group to give both).

Here’s the new setup:

Here’s the corrected .blend file:
NormalDistNode.blend (903.8 KB)

1 Like

i found i could not seem to use the above function to get the positions without the same positions repeating, i am probabally in error but already had a 2D normal slog in my code notes… it’s so short i converted it… i note my one uses floats, the above ones uses a seed?! maybe this is an error?

the one i normally use takes an x and a y from 0 to 1, then outputs back an x y now as a 2D normal… it is also just as fast to generate two numbers but does require two well generated random floats, which i belive might be why the above one accepting an integer doesn’t work for me

link to the orginal code source:

if you want to generate more than two dimensions, you can run it multiple times, you always get 2 values back to say for 3D just ignore the 4th value, it is a propper distribution this is a curisoty of this algorythm being based on a circle i belive… i am pretty sure of this as the results are shown in the second image