Skip to content Skip to sidebar Skip to footer

Applying Perlin Noise To Plane Multiple Times/ Sphere

I have some questions regarding the Perlin noise and the pv.sample_function in general. How would you go about applying Perlin noise to a sphere? I would like to have a little bit

Solution 1:

Let me answer your questions in reverse order for didactical reasons.

  1. What exactly does the third parameter in the frequency do? After playing around with some values I haven't noticed how it affected the noise.

You didn't see an effect because you were looking at 2d samples, and changing the behaviour along the third axis. The three frequencies specify the granularity of the noise along the x, y and z axes, respectively. In other words, the generated implicit function is a scalar function of three variables. It's just that your sampling reduces the dimensionality to 2.

Frequency might be a surprising quantity when it comes to spatial quantities, but it works the same way as for time. High temporal frequency means short oscillation period, low temporal frequency means long oscillation period. High spatial frequency means short wavelength, low spatial frequency means long wavelength. To be specific, wavelength and frequency are inversely proportional.

So you'll see the effect of the third frequency when you start slicing along the z axis:

import pyvista as pv

freq = [0.5, 0.5, 2]
noise = pv.perlin_noise(0.5, freq, (0, 0, 0))
noise_cube = pv.sample_function(noise,
                                bounds=(-10, 10, -10, 10, -10, 10),
                                dim=(200, 200, 200))
noise_cube.slice_orthogonal(-9, -9, -9).plot()

Three orthogonal slices of Perlin noise, showing smaller wavelength along z

As you can see, the blobs in the xy plane are circular, because the two in-plane frequencies are equal. But in both vertical planes the blobs are elongated: they are flatter in the z direction. This is because the frequency along the z axis is four times larger, leading to a wavelength that is four times smaller. This will lead to random blobs having a roughly 4:1 aspect ratio.

  1. Can you apply Perlin noise to a mesh (sphere/plane) multiple times? I would like to have a plane with some rough 'waves' and high detailed noise on top of them (thus having big waves with little waves in them).

All that happens in your snippets is that a function is sampled on a pre-defined rectangular grid, and the resulting values are stored as scalars on the grid. If you want to superimpose two functions, all you have to do is sum up the scalars from two such function calls. This will be somewhat wasteful, as you are generating the same grid twice (and discarding one of the copies), but this is the least exhausting solution from a development point of view:

defbumpy_gravel_plane():
    bounds = (-10, 2, -10, 10, -10, 10)
    dim = (500, 500, 1)

    freq = [180, 180, 50]
    noise = pv.perlin_noise(0.2, freq, (0, 0, 0))
    sampled_gravel = pv.sample_function(noise, bounds=bounds, dim=dim)

    freq = [0.5, 0.7, 0]
    noise = pv.perlin_noise(0.5, freq, (-10, -10, -10))
    sampled_bumps = pv.sample_function(noise, bounds=bounds, dim=dim)

    sampled = sampled_gravel
    sampled['scalars'] += sampled_bumps['scalars']

    smooth_and_plot(sampled)

screenshot of grid with large-scale bumps and short-scale granular texture

  1. How would you go about applying Perlin noise to a sphere? I would like to have a little bit disformed sphere.

The usual solution of generating a 2d texture and applying that to a sphere won't work here, because the noise is not periodic, so you can't easily close it like that. But if you think about it, the generated Perlin noise is a 3d function. You can just sample this 3d function directly on your sphere!

There's one small problem: I don't think you can do that with just pyvista. We'll have to get our hands slightly dirty, and by that I mean using a bare vtk method (namely EvaluateFunction() of the noise). Generate your sphere, and then query the noise function of your choice on its points. If you want the result to look symmetric, you'll have to set the same frequency along all three Cartesian axes:

defbumpy_sphere(R=10):
    freq = [0.5, 0.5, 0.5]
    noise = pv.perlin_noise(0.5, freq, (0, 0, 0))
    sampled = pv.Sphere(radius=R, phi_resolution=100, theta_resolution=100)
    # query the noise at each point manually
    sampled['scalars'] = [noise.EvaluateFunction(point) for point in sampled.points]

    smooth_and_plot(sampled)

Sphere with Perlin noisy surface warping and scalars

Post a Comment for "Applying Perlin Noise To Plane Multiple Times/ Sphere"