這次的基礎教學要介紹的是 noise 函數,和 random 函數功能相似,都是輸出一個隨機值,但和 random 不同的是,noise 可以輸出「平滑」的隨機值。

為什麼稱 noise 可以輸出「平滑」的隨機值?因為重複呼叫 random,得到的隨機值是彼此獨立的,也就是說他會在 0~1 之間亂跳:

function setup() {
  createCanvas(500, 500);

for (let x = 0; x noise([x], [y], [z])

noise 函數可以接收 1~3 個參數,用比較不精確的自然語言表述,我會把 noise 函數形容為一個顛簸的路面,但這個顛簸的路面可以是一維、二維或三維,看你要接收一個參數,兩個參數或三個參數。

現在我們試著模擬出一維的顛簸路面,這裡使用到的是接收一個參數的 noise 函數:

function setup() {
createCanvas(500, 500);

for (let x = 0; x 今天的教材借鑑一下 misvamda 大大之前的教學 Day9 – 體驗P5.js提供的幾種隨機模式 寫的程式,因為實在太適合放在這裡了,介紹了 noise 函數又結合了之前介紹的 vertex 函數,非常適合作為銜接點

現在我們要用 noise 函數搭配之前提到的 vertex 函數,實作新的動畫效果,整體看起來像是隨風飄揚的彩帶:

Imgur

從彩帶的輪廓可以很明顯得看出 noise 函數的影子,這其實和二維路面動畫是很類似的概念,用表格來歸納一下他們之間的差異:

動畫類型
位置座標
noise 數值

彩帶
x 座標和深度值
y 座標

二維路面
x, y 座標
灰度值

另外彩帶的輪廓可以用 vertex 做出 noise 曲線勾勒出來,越近的曲線給予較高的灰度值,也就是越偏白色。

反之越遠,也就是越深的曲線給予越低的灰度值,也就是越偏黑色,藉由顏色的深淺反應視覺上的距離感。

現在的問題是如何用 vertex 做出一個 noise 曲線:

function setup() {
    createCanvas(600, 600);
    background(0);

noFill(); strokeWeight(2); stroke(255);

beginShape(); for (let x = 0; x <= 600; x += 20) { let n = float(noise(x * 0.001)); let y = float(600 * n); vertex(x, y); } endShape(); }

Imgur

其實繪製 noise 曲線很簡單,只要用 vertex 對每 20 pixel 的 x 座標進行頂點標記,y 座標則套用 noise(x * 0.001) 就可以了。

然後下一步就是繪製多條 noise 曲線,建構出彩帶的視覺感:

function setup() {
    createCanvas(600, 600);
    background(0);

noFill(); strokeWeight(2); stroke(255);

for (let i = 0; i < 50; i++) { beginShape(); for (let x = 0; x <= 600; x += 20) { let n = float(noise(x 0.001, i 0.001)); let y = float(600 * n); vertex(x, y); } endShape(); } }

我們畫了 30 條 noise 曲線,每一條代表其中一個深度值,這樣就能滿足上面表格說的,用 x 座標和深度來作為 noise 函數的位置座標,所以我們呼叫 noise(x <em> 0.001, i </em> 0.01),但還是沒有根據深度調整顏色值,所以看起了沒有得到我們想要的效果。

Imgur

所以我們還要根據 i 值來調整顏色值,藉由顏色的深淺來呈現深度感:

function setup() {
    createCanvas(600, 600);
    background(0);

noFill(); strokeWeight(2);

for (let i = 0; i < 50; i++) { stroke(255 * i / 50); beginShape(); for (let x = 0; x <= 600; x += 20) { let n = float(noise(x 0.001, i 0.01)); let y = float(600 * n); vertex(x, y); } endShape(); } }

Imgur

最後再加上時間參數,就能夠實現飄逸的彩帶動畫了:

function setup() {
    createCanvas(600, 600);
    background(0);
}

function draw() { background(0); noFill(); strokeWeight(2);

for (let i = 0; i < 50; i++) { stroke(255 * i / 50); beginShape(); for (let x = 0; x <= 600; x += 20) { let n = float(noise(x 0.001, i 0.01, frameCount * 0.01)); let y = float(600 * n); vertex(x, y); } endShape(); } }

Imgur

參考資料

https://ithelp.ithome.com.tw/articles/10296797