Skip to content

3. Perlin Noise Environment Designer

Maurice Johannssen edited this page Sep 5, 2021 · 3 revisions

Introduction

So here I am having my 3D terrain. But at some point, I was a little bored by the empty looks and I thought a little more green wouldn't be bad. Thus, I wrote a small algorithm that is able to place environmental objects on basically every object. Now to realize that I also use Perlin Noise and a weight-heuristic to place the individual objects.


Implementation

My script has public arrays for grass, bushes, and trees. All items are considered a certain class and thus have a certain weight. I then iterate the x and z coordinates, since I am only interested in the xz-plane here. I then create a Perlin Noise value by inputting the x and z coordinates into the function. I then calculate an offset vector by also using Perlin Noise; for the x-coordinate, I use (x, z) as input and for the z-coordinate, I use (z, x) as input, so I just flipped that. Next, I take the offset vector '*-0.5f', since this noise function returns values between 0-1. That way, the offset goes in but + and -.

I then send a raycast downwards and check whether I hit the desired collider. After this, I check whether the dot product between the normal of the hitting triangle and an upright vector (in world space) is below a certain threshold. This way I prevent objects from being placed at points that are too steep to make sense.

After this, I take the previously generated Perlin Noise value and let it run against all weights, trying to always pick the highest one. So when I get to a point that returns a value of 0.87, I first try to place a tree, if that does not work I try to place things with a lower weight and so on, potentially placing nothing at all if that is desired of course.

I then calculate a 'slerp amount' for the rotation, so I take a random value between 0 and a configurable value, which is at most 1, to randomly rotate between being upright and the surface normal.

Lastly, I add a random rotation around the y-axis so things don't look too repetitive, creating neat results.

Clone this wiki locally