Pattern Examples

来源:互联网 发布:乡镇网络舆情监控制度 编辑:程序博客网 时间:2024/06/06 09:40

We will finish this lesson by providing you with some examples using the noise function to create various patterns. When Ken Perlin originally developped his noise function, he also proposed a few simple algorithms to generate interesting solid textures using this function as a building block. Some of these functions such as the turbulence are still widely used. He described most of these patterns and a few more in a seminal paper entitled "An Image Synthetiser" which he presented at Siggraph in 1985. This paper can easily be found on the internet and we highly recommend you to read it.


在这一课的结尾部分,我们会有一些有趣的应用例子。Ken Perlin 最初发明 PerlinNoise的时候,在论文里也给出了一些使用noise来生成有意思的贴图的算法。一些函数直到现在还在被广泛的使用中。他于1985年在Siggraph发表的论文中展示了一种名为”An Image Synthetiser“(图像合成)的算法。这篇论文很容易得到,我们强烈建议你阅读一下。


As we said earlier, our version of the noise function doesn't create the most interesting looking noise (our noise look quite blocky for now). The goal of this lesson isn't to develop a good looking noise but is to understand how the technique works and the noise's properties. Check the second Noise Part 2 for learning about a better looking version of the noise function (called gradient noise which is the original technique proposed by Ken Perlin in 1985). However that shouldn't stop us from showing you a few examples especially with the 2D noise which we can use to start creating some more complex images. We recommend that you change the parameters in the code to understand the effect they have on the result. In each of the following chapter you will find a description of the algorithm, the resulting pattern and the code used to generate this image.


之前提过,我们现在的noise function 无法生成有意思的texture, 现在的生成结果方块感十足。毕竟我们的目的是教授原理。可以通过 Noise Part 2来学习如何使用梯度noise生成更加好看的噪点贴图。( gradient noise,  Ken Perlin, 1985)现在我们开始学习如何利用噪点图生成一些复合贴图。


1D Noise Examples

One of the fist example we will describe work well in all dimensions. But we will start with the 1D case, and give an example later with 2D noise. For a 3D noise example of this technique have a look at the second lesson. The idea behind it is to sum up the contribution of several noises. We could just randomly vary the parameters of these various noise layers we are adding to each over (for example change theirfrequency and amplitude in a incoherent manner). However what we will do instead is to change these parameters in coherent manner. We will establish a connection between the change in frequency and amplitude from layer to layers. We will start from a base frequency and unit amplitude (1) and compute a first layer of noise with these values. Then we will add a second layer of noise but by multiplying the frequency of the input value by 2 and dividing its amplitude by 2. For the third layer, we will multiply the frequency by 4 and divide the amplitude by 4. Layer 4 and 5 will have their frequency and amplitude multiplied by 8 and 16 and divided by 8 and 16 respectively. If you have found the relation yet, each layer is twice the frequency and half the amplitude from the previous layer. If you build a series of noise that way and sum up together, you get the result from figure 27 (bottom image). As you can see this curve has a richer profile than a single noise. Visually it look like the profile of a mountain chain. And we are not mentioning this by mistake. As we will show later on with the 2D counterpart of this technique, we can use this result to displace a mesh and create something that looks like a mountain type landscape. Remember what we said about noise in the first chapter of this lesson. It can be used to simulate many natural shapes found in nature. This is one example.


1D Noise 例子

一个好的例子应该能在任意维度下工作。不过我们还是从1D开始吧。稍后还有2D的例子。

对于3DNoise的例子,需要参看第二部分的课程,原理上讲是综合若干个noise计算值后得出最终结果。我们可以利用随机数来调整不同noise layers 上的各个noise function。(比如用不相关的随机值作为其频率和振幅参数)。当然,实际上我们会让Layer之间的频率和振幅满足一定的相关性。
我们会使用单位频率(1)和振幅 (1) 来完成第一层的noise计算。
然后我们添加第二层noise,但是会调整noise function 的频率和振幅,2倍的频率和0.5倍的振幅。
第三层,我们使用4倍频率和0.25倍振幅。
第四层,8倍频率和 1/8 倍振幅。
第五层, 16x frequency 和 1/16 amplitude。(PS:真是...)

你能发现层之间是按2倍频率和1/2倍振幅的关系在变化。如果你像这样创建一系列的noise值,并将他们累加起来,你会得到如图27最下面所示的图像。可以看出最终合成的曲线轮廓会比单层noise细节多的多。 视觉上它看起来像一些山脉。当然这并不是错误(这就是我们想要的)。稍后我们会看到同样的技术在2DNoise中的应用,并利用noise结果来生成一些mesh ,这些mesh会形成一些山地和平原地貌。记住我们在第一章说的,Noise可以在很多模拟自然形状的地方得到应用,地形生成只是其中一种应用。


Figure 27: the fractal sum is a sum a noises which frequency and amplitude varies from layer to layer. In this example we have 5 layers. From layer to layer we double the frequency and halve the amplitude.


Before we look a bit more at the terminology, lets just say that in this example, the frequency and the amplitude of a particular layer is driven by a power of two. If we formalise the idea we just described in pseudo code, we can write:

在我们接触更多的专业术语之前,让我们看看上述基于2的幂的例子的代码:

float noiseSum = 0;static const unsigned numlayer = 5;for ( unsigned i = 0; i < numLayers; ++i ){    // change in frequency and amplitude    noiseSum += noise( P * pow( i, 2 ) ) / pow( i, 2 );}



One of the questions you might ask is how many layers shall I use to create this pattern. There is a technical answer that we will only briefly look into. When the frequency of the input value becomes really high, it is very likely that the result of the noise function will turn into white noise again (see the first chapter of this lesson, on noise properties). Which we want to avoid. You can sum up as many layers as you want until you reach the point where the frequency of the input value turns the result of the noise function into white noise. Which raises another question: do we know when that happens ? In theory yes, we can find out when this happens. This is dictated by the rules of aliasing which is a complex and large topic. You will find an explanation about this in the lesson on aliasing and filtering (basic section).

That's the theory. In practice (when we use this technique for making films) we rarely use more than 3 or 5 layers (sometimes up to 7). There's a couple of reasons for that. First computing noise is costly. So the more layers you use the more time it takes to compute. The other main reason is that, the layers might not significantly contribute to the result after we have added more than 5 of 7 layers, because the amplitude of these layers at that stage becomes really small. Why shall we use more than 5 layers if more layers do not make any significant difference while still expansive to compute ?

Ideally you want to find a compromise between theory and practice. The perfect code would sum up layers and stop automatically when it finds that the frequency of the input value for the next layer will result in white noise (see lesson on aliasing for an example of function that cut off the number of layers before in turns into white noise). An automatic system could still lead to a very high number of layers though which can be costly. It would be good to let the user control the maximum number of layers being used with an input parameter which by default would be set with the value 3, 5 or 7.


你可能会问,我需要创建多少层呢?这是存在一个技术上的方案的,我们来简单的了解下。当作为输入的值的频率变得特别高时(PS:输入数据的间隔远超 noise function当前的单位噪点间隔),noise function 的结果会退化成白噪音。这是我们希望避免的。你可以通过累加任意多层的结果,直到产生的结果变成白噪音。
这引起了另外一个问题:我们怎么直到啥时候发生了白噪音呢?理论上我们能检测到什么时候会发生。这是 aliasing 相关的问题,这是一个很复杂的内容。我们会在这节课里粗略讲解一下闪烁和过滤问题。

理论如下:在实践中(电影制作)我们很少使用超过3到5层(偶尔会用到7层)。这是有一些原因的。首先noise的计算开销比较大。所以使用的层越多,需要进行的计算就越多。另外一个主要原因是:即使使用超过5层甚至7层的层级来计算noise,实际上这些额外的层级对最终结果的影响不大。因为那些层的振幅已经衰减的十分严重了。所以如果使用更多的层会带来更多的计算开销,而结果却又没有明显不同,我们没有利用这么做。

理想情况下,你希望能在理论和实践中找到一种折中。完美的代码能够累加各layer的结果,同时在输入x的频率对于next layer来说,产生的noise会退化成白噪音时停止更多的计算。(参考 aliasing 课程上的例子函数,它会在产生白噪音的layer之前终止进一步计算)。对于一个完善的自动化机制来说,它应该允许用户自己指定一个非常大层级数量,即使这会带来更高的计算开销。它能让用户自己定义最大layer数量,并且有着默认的层级数量,比如3、5、7。

Terminology

Some terminology now. The technique of summing up layers of noise which frequency and amplitude are related to each other, can be called a fractal sum. In fact the creation of fractal curves (or surfaces) using this technique is not limited to the field of computer graphics. You may have noticed that it looks very similar to a curve that shows the evolution of the stock market over a certain period of time. These curves and their mathematical representation were studied by Benoit Mandelbrot, a mathematician well known for his research on fractal patterns (applied to the field on finance in particular). We will limit ourselves here to the introduction of a few technical terms but readers interested by this topic can read the lesson on fractal (which is by itself a fairly large and fascinating topic). Many things from the real world, landscapes, seascapes, clouds, plants, including the evolution of the stock market, etc. have a fractal form.


术语

是时候接触一些专业术语了。我们累加一些layer的noise,而这些layer的noise function在频率和振幅上满足一定的关系,这个技术叫做“fractal sum”(“分形加法”)。实际上使用此技术来创建分形曲线并不局限于计算机图形学。你可能会注意到我们之前合成的曲线看起来有点像股票市场的走势。Benoit Mandelbrot 研究过这些曲线和其数学表达式,这位数学家因对fractal patterns (分形模式)的研究为人们所熟知(特别适用于金融领域)。我们的介绍到此为止,如果想进一步了解,可以阅读关于分形的课程(这是一个相当大又十分惊艳的学科)。自然界的许多事情,陆地、海洋、云层、植物等都具有分形现象,当然也包括股票走势图。


When successive layers of a fractal noise have an amplitude which is inversely proportional to their frequency, the term used to describe the result is pink noise. If we formalise this in a formula we could write:

当一个使用多层的、分形累加的 noise function在各层的 频率和幅度满足 Amplitude = 1 / Frequency 关系时,我们称这个 Noise 为 Pink Noise(粉红噪音,Color Noise 中的一种)。如果我们公式化这个关系,表达如下: (PS:这分明是代码....)

float pinkNoise = 0;static const unsigned numlayer = 5;for ( unsigned i = 0; i < numLayers; ++i ){    // change in frequency and amplitude    pinkNoise += noise( P * pow( i, rateOfChange ) ) / pow( i, rateOfChange );}

To be a bit more specific, the change of frequency and amplitude between successive layers almost forms the signature of the result noise curve. It defines it spectral properties. We use the term spectral densities to define the various frequencies (layers) the resulting noise is made of. And each one of these layers has a specific amplitude which we call power spectra. Amplitude and frequency can either be related to each other like in the case of pink noise or not. There might also exist a relation in the change of frequency between successive layers. These observations are key to the creation of many patterns in computer graphics and we recommend you understand this well before reading any other lessons on pattern creation.

具体的说,频率和振幅在连续层级上的变化形成了曲线的特征图像。这个特征定义了曲线的谱特性。我们使用名词 “spectral densities” (谱密度)来表达不同层级上的频率。而每个层级的振幅,我们用名词 “ power spectral” (功率谱) 来代指。频率和振幅的关系可以遵循pink noise 的 1/f ,也可以不遵循。在连续层的频率变化中也可能存在一个关系。对这些关系的观察是在计算机图形学中创造了许多图形的关键,我们建议你在阅读其他课程之前,理解这一类的课程。(PS:信号处理有讲 Color Noise)

PS: 功率 * 频率 = 携带的能量 , 所以 1/f 粉红噪音 在所有频率上的能量相等。
PS2: 上面是我瞎理解的,可能有错误,但是谁在乎粉红噪音为什么有能量相等的特性~ 我只需要知道 a = 1/f.

We can create a complex noise function (fractal sum) from summing up a series of basic noises which frequencies are related to each other. The frequency of a layer and its amplitude are also connected. If we can do that, it means that the reverse process might be possible as well. Meaning we can take a signal that seems to be fractal and decompose it into simpler noise functions to find out what is the frequency ratio between two consecutive layers (what are the different frequencies the signal is made of and what is the relation between these frequencies if one exists) as well as the ratio frequency-amplitude for each layer. Doing so will make it possible to establish the spectral properties of that signal. This observation is key in the development of algorithms used for simulating ocean surfaces in particular. If we know the spectral densities of certain patterns in nature then we can very likely recreate them with a computer and obtain similar patterns (this process is similar to the concept of spectral modeling synthesis in acoustic). This is a very cool observation which has been widely used in CG since at least the mid 80's.


我们在一组noise 函数上,使其频率参数在连续层级保持一定的关系,并对各层级的计算结果使用分形加法,创建了一个复杂的Noise Function。而且频率和振幅之间也满足一定关系。如果我们做到了这些相关性,意味着我们可以反向处理一个可能是分形结果的噪声信号,并将它分解到一个简单的Noise函数,并计算出连续layers之间的频率变化率。(PS:上百度翻译了啊,剩下基本就是在说频谱分析...)(什么是不同的频率的信号是由什么和什么是这些频率之间的关系,如果一个存在),以及为每一层的频率振幅。这样做将有可能建立该信号的频谱特性。这种观察是在特定的模拟海洋表面的算法的发展的关键。如果我们知道某些模式在本质上的光谱密度,那么我们就可以很有可能重新建立他们与计算机和获得类似的模式(这个过程是类似的概念,频谱建模合成的声音)。这是一个非常酷的观察,已广泛应用于CG至少自80年代中期。

The use of the word noise in the name (pink noise) might be a bit misleading as it refers to a sum of noise functions with correlated frequencies and amplitudes. The term octave is also sometimes (mis-)used in place of the word layer. The term layer is more generic than octave which is also used in music. An octave is a doubling or having of a frequency. If it is used in a program (or in literature) it should mean that each successive layer in the computation of a fractal sum is twice the frequency of the previous layer. It means that the term change of rate in our equation would take the value 2. If the frequency ratio between successive layers is different than 2, the use of this term is inaccurate and layer should be used instead. When we double the frequency between layers and that the amplitude of these layers is inversely proportional to their frequency, we obtain a special type of pink noise which we call Brownian noise (named after the mathematician Robert Brown).

我们对特殊noise的命名方式可能有点误导(比如粉红噪音)。 它是一组在频率和振幅上有相关性的Noise Function结果的分形累加。有的地方会用octave(八度音阶)来代替layer(层),这也是不准确的。 layer 所定义的层级之间的关系比 octave 要更加普适。 在音乐上也使用octave这个名词。一高一个octave代表着频率提高到原来的2倍。如果使用 octave来实现noise function,意味着某一层层的频率是前一层频率的两倍。这也就是说变化率是2.(PS: f(k) = f(k-1) * 2 里的2)。 如果变化率不是2,就应该使用layer来进行描述。 如果一个noise的频率满足2倍变化率,而且频率和振幅的关系成导数,我们就得到了一种特殊的 pink noise,名为 Brownian Noise(布朗噪音-也成Red Noise)(以数学家Robert Brown命名)。

float brownianNoise = 0;static const unsigned numlayer = 5;float rateOfChange = 2;for ( unsigned i = 0; i < numLayers; ++i ){    // change in frequency and amplitude    brownianNoise += noise( P * pow( i, rateOfChange ) ) / pow( i, rateOfChange );}

In computer graphics, you will often find that fractal functions are called fBm (which stands for fractional brownian motion). The CG community has borrowed most of these terms from the mathematics field, mainly as a convenient way of labelling functions which are using these techniques in a generally simplified/simpler form. In the generic form of the fBm function, the amplitude of a layer doesn't have to be inversionaly proportional to its frequency. You can use two different values to control how the frequency and the amplitude change between layers. The word lacunarity is used to control the rate by which the frequency changes from layer to layer. Lacunarity has a special meaning in in the field of fractal (check the lesson on fractals from more information). There is no special word for the rate of change in the amplitude from layer to layer. We will be using gain in the following pseudo-code of an fBm function:


在计算机图形学(CG)领域,你会经常看到一些Fractal Functions(分形函数),这类函数一般都叫做 fBm( fractal brownian motion 分形布朗运动)。CG学科从数学领域借用了大量的专业名词,主要是为了给特定函数指定一个好记的标签,便于以更加简化/简单的形式来使用那些技术。在一个fBm函数的一般表达形式中, 同一层的振幅和频率不一定是倒数关系。你完全可以使用两个值来分别控制频率和振幅在不同层之间的变化方式(PS:pink noise规定了振幅和频率的关系,所以我们只需要改变一个就可以推算出另外一个)。Lacunarity(孔隙度)是分形领域一个专有名词(查看其它分形课程以获得更多信息)。对于振幅关系,没有专门的名词来代指它们之间的关系,我们在这里使用gain这个名词来代指振幅的关系。代码如下:

float fBm( Point P, float lacunarity = 2, float gain = 0.5, int numLayers = 5 ){    float noiseSum = 0;    Point noiseP = P;    float amplitude = 1;    for ( unsigned i = 0; i < numLayers; ++i )    {        // change in frequency and amplitude        noiseSum += noise( noiseP ) * amplitude;        noiseP *= lacunarity;        amplitude *= gain;    }    return noiseSum;}


PS:  Lacunarity 孔隙度 ,来自拉丁语,分形上使用 \lambda 来表达一个分形结果的孔隙度。lacunarity 是用来分析分形结果的。
关于Lacunarity没有统一的测量标准,比较常用的一种是 Box Counting Lacunarity。
对于一张 Fractal Texture, 我们利用一个指定大小的Box,对这张图划分成grid。计算每个Cell里的值的标准方差 standard deviation。我们规定一个"孔"的评测标准,比如一个固定的值,凡是像素低于此值,都认为是孔,等于或高于此值,都认为是有效值(value)。
cell lacunarity = (standard deviation / value count)^2

这样我们就可以定量的分析每个cell之间的差异了。在CG领域,lacunarity一般用于插值,因为分形图像在某些地方的连续性不尽如人意,这时根据 lacunarity 作为分析工具,进行插值运算,可以平滑一些不想要的结果(具体步骤不清楚)。Box Counting 的box,可以是紧密排列的grid ,也可以以固定步长在图像上移动,得到的结果精细度不同而已。


Now that we have established these basic concepts for 1D noise, lets see what happens when we apply the same techniques to a 2D noise.

现在我们已经有了1DNoise相关的基本概念的认识。让我们看看同样的技术应用在2DNoise时的情况。


2D Noise Examples

To make our program easier to use we will first create a simple generic function that will will loop other all the pixels of an image and compute a 2D position from it. The pixel color is set with the result of our noise function for that point. This function is a template which takes a noise function as an argument. The noise function is where we will implement the code to compute various patterns (download the source code for a complete example).

2D Noise 例子

为了让我们的程序用起来方便,我们会先写一个简单的泛型函数,它负责创建指定大小的Texture ,并根据2D位置计算每一个像素的值。像素的值会根据我们的Noise Function 来进行计算。这个函数将NoiseFunction作为模板参数。我们会通过传递不同的NoiseFunction实现来展示若干种图像模式。

(PS:模板参数的类型是函数指针,这个技巧可能对C++基础不太好的同学难以理解,你可以认为是在每个像素位置上调用了一次NoiseFunction)。


template<NoiseFunc N>void CreateNoiseImage( const char *filename ){    Simple2DNoiseB simpleNoise2D;    unsigned imageWidth = 512, imageHeight = 512;    float invImageWidth = 1.f / imageWidth, imvImageHeight = 1.f / imageHeight;    float *imageBuffer = new float[ imageWidth * imageHeight ];    float *currPixel = imageBuffer;    for ( unsigned j = 0; j < imageHeight; ++j )    {        for ( unsigned i = 0; i < imageWidth; ++i )        {            Point2f P = Point2f( i * invImageWidth, j * imvImageHeight ) * 5;            *currPixel = (*N)( simpleNoise2D, P );            currPixel++;        }    }    SaveImage( filename, imageBuffer, imageWidth, imageHeight );    delete [] imageBuffer;}

Simple 2D Noise

Our first example is trivial. To demonstrate the use of our program and test our noise function we first output a simple noise image. The function called makes a noise lookup using the point with its basic frequency as an input.


简单的2DNoise

我们首先来一张普通的。这是使用单一Noise Layer 生成的图像,频率和振幅都是1。


inline float SimpleNoise( const Simple2DNoiseB &simple2DNoise, const Point2f &P ){    return simple2DNoise.eval( P );}


Fractal Sum

Our second example is a demonstration of the fractal sum that we have already explained for the 1D case. We accumulate the contribution of five layers of noise. Between each successive layer we multiply the frequency of the point from the previous layer by two and divide the amplitude from the previous layer by two.

分形累加

第二个例子是使用我们在1DNoise部分解释过的分形累加技术。我们使用了5个Layers。 频率和振幅的关系 为 a = 1/f , 不同layer之间的频率关系为2. (PS: Red Noise , 布朗噪音)

Figure 28: example of a fractal sum using 2D noise. The principle is the same as with the 1D example. Layer n + 1 has twice the frequency and half the amplitude of layer n.

图28:布朗噪音(注意关系)

Here is the resulting image and the code used to compute this result (the code is already slightly optimised. We could have used the function pow(2, k) to change the frequency and the amplitude of the noise function. But this function is quite slow and we can replace it with a recursive multiplication of the frequency (2) and amplitude (0.5) parameters):


这里是一张结果图。


float FractalNoise( const Simple2DNoiseB &simple2DNoise, const Point2f &P ){    static const unsigned numLayers = 5;    float frequency = 1;    float amplitude = 1;    float fractalNoise = 0;    float maxSum = 0;    for ( unsigned k = 0; k < numLayers; ++k )    {        maxSum += amplitude;        fractalNoise += simple2DNoise.eval( P * frequency ) * amplitude;        amplitude *= 0.5;        frequency *= 2;    }    // normalise the result    return fractalNoise / maxSum;}

As mentioned before the fractal sum can be used to create convincing terrains and many other natural patterns (seascapes, landscapes, etc.). We can easily create a 2D texture and use it to displace a mesh (figure xx). More details can be found in the lessons on texture synthesis, terrain generation and modelling of ocean surfaces.

我们使用这种2D噪音贴图用来作为生成海洋、陆地、、云之类的模型。这种技术称为 texture synthesis (纹理合成)。


Figure 29: fractal noise can be used to generate terrain by texture displacement. It can be used for generating terrain like in this example but also water surfaces or clouds. Check the lessons on displacement and terrain generation.

图29:基于分形噪音技术制作的模型。


In the code you can experiment by changing the multiplier for the frequency and the amplitude, turning your fractal noise function into a more generic fBm function which we have described earlier on.

下列代码中,你可以通过控制 频率、振幅之间的倍数,将函数变成一个更加一般化的 fBm 函数 ( fractal Brownian movtion)。


float fBm( const Simple2DNoiseB &simple2DNoise, const Point2f &P ){    static const unsigned numLayers = 5;    float frequency = 1;    float amplitude = 1;    float fractalNoise = 0;    float lacunarity = 1.3;    float gain = 0.6;    float maxSum = 0;    for ( unsigned k = 0; k < numLayers; ++k )    {        maxSum += amplitude;        fractalNoise += simple2DNoise.eval( P * frequency ) * amplitude;        amplitude *= gain;        frequency *= lacunarity;    }    // normalise the result    return fractalNoise / maxSum;}


Many different looks can be achieved by varying the value for the lacunarity and the gain as showed in the next figure.

通过控制 gain 和 lacunarity 参数可以得到很多不同的结果,如下图。

Figure 30: many interesting patterns can be created by changing the values for the lacunarity and the gain.

图30:只调整 lacunarity 和 gain 时的几种不同效果。


Turbulence

Turbulence is a function built on the same principle as the fractal sum. However instead of using the noise function directly for each layer, we will use the absolute value of the signed noise. We will first convert the result of the noise into a signed noise, and then take the absolute value of this result. As you can see in the following figure, processing the noise function that way, creates a profile that seems to be made of bumps. Wherever the curve is negative (black line) we will mirror the curve in these areas along the x axis. The red line curve is the result. Using this technique with a 2D noise can produce patterns suitable to simulate fire, smoke or clouds. 

湍流

trubulence(湍流函数)是建立在分形累加原理上的一种噪音生成函数。它不是直接将每层的noise function函数产生的值,而是使用带符号的noise,并且对结果取绝对值。(PS:普通的noise function 产生[0:1]的输出,你可以通过调整频率、振幅和相位产生[-1,1]的输出,比如 2 * f(x) -1)
下图所示是经过这样处理后的结果的曲线(PS: 黑色直线是y=0,上半部分是湍流函数的曲线)。
用这种技术生成的2DNoise很适合用来模拟火焰、烟雾和云。


Figure 30: turbulence works like the fractal sum but instead of using the noise function directly, we use the absolute value of a signed noise. In blue, the original signed noise for the first layer. Wherever the curve is negative we mirror its values about the x-axis. The resulting curves (in red, which overlaps the blue curve when the signed noise is positive) looks bumpy.

图30:黑色直线是y=0,上半部分是湍流函数的曲线,红色部分是蓝色部分相对x轴的镜像。



inline float SignedNoise( const Simple2DNoiseB &simple2DNoise, const Point2f &P ){    return ( 2 * simple2DNoise.eval( P ) - 1 );}     // Can be used to create flame/fire effectfloat TurbulenceNoise( const Simple2DNoiseB &simple2DNoise, const Point2f &P ){    static const unsigned numLayers = 5;    float frequency = 1;    float amplitude = 1;    float turbulenceNoise = 0;    float maxSum = 0;    for ( unsigned k = 0; k < numLayers; ++k )    {        <span style="background-color: rgb(0, 204, 204);">maxSum += amplitude;</span>        turbulenceNoise += <span style="background-color: rgb(0, 204, 204);">fabs(</span> SignedNoise( simple2DNoise, P * frequency ) <span style="background-color: rgb(0, 204, 204);">)</span> * amplitude;        amplitude *= 0.5;        frequency *= 2;    }    // normalise the result    return turbulenceNoise / <span style="background-color: rgb(0, 204, 204);">maxSum;</span>}

Marble Texture

A marble texture can created by modulating the phase of sine pattern with a noise function or a fractal sum. The idea here is not to use the noise function directly to create the pattern but to perturb the function we are using to create the pattern. In that case, we perturb or shift the phase of the sine function with a fractal sum. This idea can be use to introduce randomness in any periodic or regular function. Our example is quite simple and only draw a black and white marble texture. However by introducing some color in the mix, it might be possible to create more realistic patterns. The lesson on texture synthesis contains more sophisticated examples.

大理石纹理

大理石纹理是利用一个sine函数作为外层函数,其参数输入则使用一个Noise Function 或一个 分形累加噪音函数,通过调整这个sine函数的周期、相位和振幅来得到的结果。基本思想是用噪音函数作为周期函数的输入。这种思路可以在任何周期或规则函数里引入随机性。(PS:从整体趋势上又能维持原有函数的特征)。我们的函数只是简单的绘制了黑白的大理石纹理。 如果再添加点其他颜色的混合,也许能产生更加真实的效果。纹理合成课程上有更加精细的例子。


float MarbleNoise( const Simple2DNoiseB &simple2DNoise, const Point2f &P ){    // sin goes from -1 to 1 so remap to [0:1]    return (<span style="background-color: rgb(0, 204, 204);"> sin(</span> P.x * 4 + FractalNoise( simple2DNoise, P * 0.5 ) * 4 ) + 1 <span style="background-color: rgb(0, 204, 204);">)</span> * 0.5;}

Wood Texture

Like the marble texture, the wood texture relies on a very simple trick. The idea is to multiply the noise function by a certain value greater than 1. Lets call the result of this multiplication g (historically it was called g in reference to wood grain). The texture is obtained by subtracting g from its integer part. Casting a positive float number to an integer will result in an integer necessarily smaller or equal to g. The result of that subtraction is therefore necessarily in the range [0:1) (1 exclusive). Figure xx illustrates the process. In this example, we have multiplied the noise function by 4. The blue curve represents the value g, while the red curve represents the result of subtracting g from its integer part. Multiplying the noise function by a value greater than 4 would result in more breakups in the red curve. In 2D, these breakups mark the boundary between regions of lighter and darker color (see the image below).

树木年轮纹理

和大理石纹理类似,年轮纹理只是应用了一个简单的技巧。思路是给noise function 的结果乘以一个大于1的值,再对结果取它的小数部分。
下图是 乘以4的效果。

Figure 31: the blue curve is the result of the noise multiplied by 4. The red curve is the result of the wood texture function. We subtract the blue curve from its integer part.


float WoodNoise( const Simple2DNoiseB &simple2DNoise, const Point2f &P ){    float g = simple2DNoise.eval( P ) * 10;    return g - int( g );}


References

An Image Synthesizer. Ken Perlin (1985)

Texturing and Modeling, Third Edition: A Procedural Approach. David S. Ebert, F. Kenton Musgrave, Darwyn Peachey, Ken Perlin, Steve Worley (2002)

The Science of Fractal Images, Heinz-Otto Peitgen (1988)




我终于弄懂了!!!现在去编码啦~~~~开森。


0 0
原创粉丝点击