多次将柏林噪声应用于平面/球体 [英] Applying Perlin noise to plane multiple times/ sphere

查看:31
本文介绍了多次将柏林噪声应用于平面/球体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对 Perlin 噪声和 pv.sample_function 有一些疑问.

  1. 您将如何将柏林噪声应用于球体?我想要一个有点变形的球体.
  2. 您能否将 Perlin 噪声多次应用于网格(球体/平面)?我想要一架飞机,上面有一些粗糙的波浪"和高细节噪声(因此有大波浪和小波浪).
  3. 频率中的第三个参数究竟有什么作用?在尝试了一些值之后,我没有注意到它是如何影响噪音的.

这是我想应用于一个平面的两种不同频率/柏林噪声.此外,它还显示了他们分别创建的平面.

def smooth_and_plot(采样:pv.core.grid.UniformGrid):网格 = sampled.warp_by_scalar('scalars')网格 = mesh.extract_surface()# 清洁和平滑一点以减少柏林噪声伪影网格 = mesh.smooth(n_iter=100,就地=真,relaxation_factor=0.07)网格.plot()defgravel_plane():频率 = [180, 180, 50]噪声 = pv.perlin_noise(0.2, freq, (0, 0, 0))采样 = pv.sample_function(噪音,界限=(-10, 2, -10, 10, -10, 10),暗淡=(500, 500, 1))smooth_and_plot(采样)定义颠簸_平面():频率 = [0.5, 0.7, 0]噪声 = pv.perlin_noise(0.5, freq, (-10, -10, -10))采样 = pv.sample_function(噪音,界限=(-10, 2, -10, 10, -10, 10),暗淡=(500, 500, 1))smooth_and_plot(采样)

解决方案

出于教学原因,让我以相反的顺序回答您的问题.

<块引用>

  1. 频率中的第三个参数究竟有什么作用?在尝试了一些值之后,我没有注意到它是如何影响噪音的.

您没有看到效果,因为您正在查看 2d 样本,并沿第三个轴更改行为.这三个频率分别指定了沿 x、y 和 z 轴的噪声粒度.换句话说,生成的隐函数是三个变量的标量函数.只是您的采样将维数降低到 2.

就空间量而言,频率可能是一个令人惊讶的数量,但它的工作方式与时间相同.时间频率高意味着振荡周期短,时间频率低意味着振荡周期长.高空间频率意味着短波长,低空间频率意味着长波长.具体来说,波长和频率成反比.

所以当您开始沿 z 轴切片时,您将看到第三个频率的效果:

导入pyvista为pv频率 = [0.5, 0.5, 2]噪声 = pv.perlin_noise(0.5, freq, (0, 0, 0))noise_cube = pv.sample_function(噪音,界限=(-10, 10, -10, 10, -10, 10),暗淡=(200、200、200))noise_cube.slice_orthogonal(-9, -9, -9).plot()

如您所见,xy 平面中的斑点是圆形的,因为两个平面内频率相等.但是在两个垂直平面中,斑点都被拉长:它们在 z 方向上更平坦.这是因为沿 z 轴的频率大四倍,导致波长小四倍.这将导致随机 blob 的纵横比约为 4:1.

<块引用>

  1. 您能否将 Perlin 噪声多次应用于网格(球体/平面)?我想要一架飞机,上面有一些粗糙的波浪"和高细节噪声(因此有大波浪和小波浪).

在您的代码片段中发生的所有事情是在预定义的矩形网格上对函数进行采样,并将结果值作为标量存储在网格上.如果你想叠加两个函数,你所要做的就是将两个这样的函数调用的标量相加.这会有点浪费,因为您要生成两次相同的网格(并丢弃其中一个副本),但从开发的角度来看,这是最不费力的解决方案:

defbumpy_gravel_plane():边界 = (-10, 2, -10, 10, -10, 10)暗淡 = (500, 500, 1)频率 = [180, 180, 50]噪声 = pv.perlin_noise(0.2, freq, (0, 0, 0))sampled_gravel = pv.sample_function(噪音,边界=边界,暗淡=暗淡)频率 = [0.5, 0.7, 0]噪声 = pv.perlin_noise(0.5, freq, (-10, -10, -10))sampled_bumps = pv.sample_function(噪音,边界=边界,暗淡=暗淡)采样 = sampled_gravel采样['标量'] += 采样_凹凸['标量']smooth_and_plot(采样)

<块引用>

  1. 您将如何将柏林噪声应用于球体?我想要一个有点变形的球体.

生成 2d 纹理并将其应用于球体的常用解决方案在这里不起作用,因为噪声不是周期性的,因此您不能像那样轻松地关闭它.但是仔细想想,生成的 Perlin 噪声是一个 3d 函数.您可以直接在球体上对这个 3d 函数进行采样!

有一个小问题:我认为仅使用 pyvista 无法做到这一点.我们将不得不稍微弄脏我们的手,我的意思是使用一个简单的 vtk 方法(即噪声的 EvaluateFunction()).生成您的球体,然后在其点上查询您选择的噪声函数.如果您希望结果看起来对称,则必须沿所有三个笛卡尔轴设置相同的频率:

defbumpy_sphere(R=10):频率 = [0.5, 0.5, 0.5]噪声 = pv.perlin_noise(0.5, freq, (0, 0, 0))采样 = pv.Sphere(半径=R,phi_resolution=100,theta_resolution=100)# 手动查询每个点的噪声sampled['scalars'] = [noise.EvaluateFunction(point) for point in sampled.points]smooth_and_plot(采样)

I have some questions regarding the Perlin noise and the pv.sample_function in general.

  1. How would you go about applying Perlin noise to a sphere? I would like to have a little bit disformed sphere.
  2. 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).
  3. 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.

These are the two different frequencies/Perlin noises that I would like to apply to one plane. Additionally, it shows the plane they respectively create.

def smooth_and_plot(sampled : pv.core.grid.UniformGrid):
    mesh = sampled.warp_by_scalar('scalars')
    mesh = mesh.extract_surface()

    # clean and smooth a little to reduce perlin noise artifacts
    mesh = mesh.smooth(n_iter=100, inplace=True, relaxation_factor=0.07)
    mesh.plot()


def gravel_plane():
    freq = [180, 180, 50]
    noise = pv.perlin_noise(0.2, freq, (0, 0, 0))
    sampled = pv.sample_function(noise,
                                 bounds=(-10, 2, -10, 10, -10, 10),
                                 dim=(500, 500, 1))

    smooth_and_plot(sampled)


def bumpy_plane():
    freq = [0.5, 0.7, 0]
    noise = pv.perlin_noise(0.5, freq, (-10, -10, -10))
    sampled = pv.sample_function(noise,
                                 bounds=(-10, 2, -10, 10, -10, 10),
                                 dim=(500, 500, 1))

    smooth_and_plot(sampled)

解决方案

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()

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:

def bumpy_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)

  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:

def bumpy_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)

这篇关于多次将柏林噪声应用于平面/球体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆