基於p5.js
繪製的頁面算法
用於程序模擬生成天然紋理。api
柏林噪聲是一個很是強大算法,常常用於程序生成隨機內容,在遊戲和其餘像電影等多媒體領域普遍應用dom
柏林噪聲絕大部分應用在2維,3維層面上,但某種意義上也能拓展到4維。柏林噪聲在1維層面上可用於卷軸地形、模擬手繪線條等。
若是將柏林噪聲拓展到4維層面,以第4維,即w軸表明時間,就能利用柏林噪聲作動畫。例如,2D柏林噪聲能夠經過插值生成地形,而3D柏林噪聲則能夠模擬海平面上起伏的波浪。下面是柏林噪聲在不一樣維度的圖像以及在遊戲中的應用場景。函數
360度的範圍oop
函數繪製器動畫
咱們能夠查看週期(0.8,0,0.4)這個範圍內起伏變化的this
2π
大概6.283的大體範圍spa
noiseDetail(x,y)
code
語法 noiseDetail(lod, falloff) 參數 lod 數字:噪音該使用的八度數 falloff 數字:每一個八度的衰退因數
默認 noiseDetail(0.5, 0.75)
blog
第一個八度的影響力爲 50% 。這衰退值能經過加多一個參數而改變。好比說若是衰退因數爲 0.75 那表示每一個八度將會有其前者的 75% 的影響力(減小 25%),是否是摸不着頭腦
任何介於 0.0 與 1.0 的值都能被接受,不過注意高於 0.5 的值可能會形成 noise() 函數會返回大於 1.0 的值。
noise(x,y)
噪聲值
柏林噪聲與 random() 函數最主要的不一樣點在於前者是在一個無限的 n 維空間內定義的,這空間內每一對座標都相對於一個固定的半隨機值(
noiseSedd()函數
)返回的值必定會在 0.0 至 1.0 之間
輸入座標的值並不重要,只有個別座標之間的距離須要被注意(如在循環內使用 noise() 時)。
通常來講座標之間的距離越小,生成噪聲隨機數列將會越平滑。介於 0.005-0.03 之間的距離應該適合大多數應用場合
// 根據上面的能夠知道,減小0.2 noiseDetail(1, .8) // radians(deg) 角度轉成弧度 // TWO_PI 2π for (let i = 0; i < TWO_PI; i += radians(1)) { let x = this.offset * cos(i) + this.offset let y = this.offset * sin(i) + this.offset // 因爲偏移值 0.4 // 起點 // 0.8 0.4 console.log(x,y,noise(x, y));
beginShape()
endShape()
記錄建立形狀的頂點,中止記錄
beginShape(); vertex(20, 20); vertex(40, 20); vertex(40, 40); vertex(60, 40); vertex(60, 60); vertex(20, 60); endShape(CLOSE);
push(), pop()
push(); // 啓動一個新的繪製狀態 strokeWeight(10); fill(204, 153, 0); translate(50, 0); ellipse(0, 50, 33, 33); // Middle circle pop(); // 恢復原始狀態
radians(deg)
角度轉成弧度
map
map(值,開始,結束,開始,結束) 例如 個人鼠標x, 0到最大的寬度內,展現0-255的值 let num=map(mouseX,0,width,0,255) 看了源碼好像相似於線性插值,線性插值能夠看以前的文章 (n, start1, stop1, start2, stop2) newval = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2;
const shadowColor = 'rgba(0,0,0,0.05)' class lotusLeaf { constructor(x, y, offset, scale) { this.x = x this.y = y this.offset = offset this.scale = scale this.color = color(71, 184, 151) } drawShape(vertices, offset, color) { fill(color) beginShape() vertices.map(v => vertex(v.x + offset, v.y + offset)) endShape() } show() { push() translate(this.x, this.y) noiseDetail(1, .8) let vertices = [] // radians(deg) 角度轉成弧度 for (let i = 0; i < TWO_PI; i += radians(1)) { let x = this.offset * cos(i) + this.offset let y = this.offset * sin(i) + this.offset let r = 180 + map(noise(x, y), 0, 1, -this.scale, this.scale) console.log(r); let x1 = r * cos(i) let y1 = r * sin(i) vertices.push({x: x1, y: y1}) } noStroke() //當前荷葉 this.drawShape(vertices, 0, this.color) // 偏移值用於繪製,荷葉陰影 this.drawShape(vertices, 50, shadowColor) // 繪製荷葉上的紋理 vertices.map((v, index) => { //根莖有9個 if ((index + 1) % 40 === 0) { strokeWeight(6) stroke(23,111,88,40) // x,y 是最外點, 就是圓點,當前點的距離 line(v.x * .1, v.y * .19, v.x * .9, v.y * .86) } }) pop() } } function setup() { createCanvas(windowWidth, windowHeight) background(230) new lotusLeaf(100, 100, 0.4, 100).show() } function draw() { }
咱們發現陰影顯示了,其實咱們應該先畫陰影再畫荷葉就不會出現這種狀況,由於陰影被荷葉覆蓋掉了
默認幀率1s 60幀
向量
pos=createVector(width/2,height/2) pos.x pos.y 這樣使用
代碼
/*================== 漣漪 ===================*/ class Ripple { constructor(x, y) { this.position = createVector(x, y) this.size = random(50, 100) // 透明度的值 this.lifespan = 255 this.color = color(255, 255, 255) this.sizeStep = random(2, 3) // 顯示的時間 this.lifeStep = random(2, 10) } drawShape(x, y, offset, size, color) { stroke(color) strokeWeight(1) noFill() circle(x + offset, y + offset, size) } show() { // 設置顏色透明度 this.color.setAlpha(this.lifespan) // 當前圓,顏色白色 this.drawShape(this.position.x, this.position.y, 0, this.size, this.color) //偏移50的圓,顏色另外一種 this.drawShape(this.position.x, this.position.y, 50, this.size, color(shadowColor)) } update() { // 圓變大 this.size += this.sizeStep // 時間變短 this.lifespan -= this.lifeStep } } const ripples = [] const shadowColor = 'rgba(0,0,0,0.05)' function setup() { createCanvas(windowWidth, windowHeight) background(230) } function draw() { background(230) //默認幀率60, 就是每s執行兩次 if (frameCount % 30 === 0) ripples.push(new Ripple(random(width), random(height))) ripples.forEach((r, i) => { r.update() r.show() // 若是沒有啦 再添加一個漣漪 if (r.lifespan < 0 ) ripples.splice(i, 1) }) } function windowResized() { resizeCanvas(windowWidth, windowHeight); background(230); }