iT邦幫忙

DAY 9
1

用程式描繪世界 - 閱讀The Nature of Code系列 第 9

[Day9] - 二維的Perlin Noise

  • 分享至 

  • xImage
  •  

上一篇介紹了Perlin Noise,但僅限一維的Perlin Noise,一維的概念是由傳入俱有連續性的參數去產生noise,不過這有一個限制在於,你所能建構出的noise,只會與他的上一個noise與下一個noise產生關聯,如圖:

但如果是使用二維的方式,他的四面八方都可以與它產生關聯,如下圖:


如果我們可以控制一的點臨近八個方向的像素,使他們產生關聯,就可以用來模擬自然界中的紋路,那要怎麼在程式中做到呢?

我們可以先從Random開始,用巢狀迴圈將每個像素給一個隨機的灰度值,建立一個二維的隨機雜訊圖,如下

void setup(){
  size(300,300);
  loadPixels();
  for (int x = 0; x < width; x++) {
    float yoff = 0.0;
    for (int y = 0; y < height; y++) {
      float bright = random(255);
      pixels[x+y*width] = color(bright);
    }
  }
  updatePixels();
}

loadPixel()與updatePixels()使之前沒看過的兩個方法,loadPixel()的主要功用是將目前畫面上的像素load進pixels[]的array中,之後就可以進行更改,
並用updatePixels(),更新到畫面上。

上面的方式因為使用random()作為產生noise的方式,所以結果就會像電視的雜訊一樣,非常雜訊~

如果要讓每一個像素之間產生關聯,只需要將random()替換成noise的方法,並mapping到灰度的範圍(0 ~ 255)上。

map( noise(x,y), 0, 1, 0, 255)

結果如下:

還是有一點怪怪的,不是那麼的平滑,預計想要產生的圖形是類似雲狀的,那為什麼沒有產生預期的結果呢?

是因為在迴圈中,noise所帶入的參數相差太多,這一次的x值與下一次的x值相差是1,因此生出的圖像像素之間關聯性還是很低,解決的辦法是必須另外寫兩個參數去管理代入noise的值,創出xOffset與yOffset,在迴圈內讓他們只增加0.01,這樣就可以了

void setup(){
  float xOffset = 0.0;
  size(300,300);
  loadPixels();
  for (int x = 0; x < width; x++) {
    float yOffset = 0.0;
    for (int y = 0; y < height; y++) {
//      float bright = random(255);
//      float bright = map( noise(x,y), 0, 1, 0, 255);
        float bright = map(noise(xOffset, yOffset),0,1,0,255);
      pixels[x+y*width] = color(bright);
      yOffset += 0.01;
    }
    xOffset += 0.01;
  }
  updatePixels();
}

圖案如下:

這是一個雲狀的圖形,但是我們可以藉由改變參數,例如noise代入的參數每次所增加值,或是增加色參數的控制,去改變產生的圖形,模擬出如大理石、木頭... 等等的材質。


上面是我改變了y軸的參數,讓他每次增加0.1,有點像木頭質地了,真是神奇,加上褐色應該會更像。

介紹完了一系列關於機率(propability)、分佈(distribution)與噪聲(noise),書上所說,這些不過只是產生“數值”的方法,實際上可以把它應用在各個不同的情境,比如說Perlin Noise也可以應用在枝葉的搖擺、或是控制物體流動的速度與方向。

下一篇開始介紹向量(Vector)


上一篇
[Day8] - 平滑移動 (Perlin Noise)
系列文
用程式描繪世界 - 閱讀The Nature of Code9
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言