柏林噪声双线性插值初步了解(js)
生活随笔
收集整理的這篇文章主要介紹了
柏林噪声双线性插值初步了解(js)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
效果
js代碼
可直接執行,不做過多解釋,了解更多按照順序點擊最后面的參考鏈接
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>雙線性插值</title> </head> <body> <canvas id="cv" width="1400px" height="1400px"></canvas> <script>/*==================================工具==================================*//**柏林函數*/function fade(t) {return t * t * t * (t * (t * 6 - 15) + 10)}/**插值,默認使用柏林函數作為平滑函數*/function lerp(a, b, weight, type) {//根據不同的type 選擇不同的平滑方式if (!type) {return a + (b - a) * fade(weight);}if (type == 1) {return a + (b - a) * weight}if (type == 2) {return a + (b - a) * lerp(Math.sin(weight), fade(weight), 0.5, 1)}}/*** 向量點乘*/function dp(v1, v2) {return v1.x * v2.x + v1.y * v2.y}/*** 區間映射,不考慮錯誤的使用方式*/function mirror(data, fa, fb, ta, tb) {return ta + (data - fa) / (fb - fa) * (tb - ta)}/*** 隨機二維數*/function hash22(x, y) {let arr = [];arr[0] = x * 127.1 + y * 311.7;arr[1] = x * 269.5 + y * 183.3;let sin0 = Math.sin(arr[0]) * 43758.5453123;let sin1 = Math.sin(arr[1]) * 43758.5453123;arr[0] = (sin0 - Math.floor(sin0)) * 2.0 - 1.0;arr[1] = (sin1 - Math.floor(sin1)) * 2.0 - 1.0;// 歸一化,盡量消除正方形的方向性偏差let len = Math.sqrt(arr[0] * arr[0] + arr[1] * arr[1]);arr[0] /= len;arr[1] /= len;return {x: arr[0], y: arr[1]};}/*** 生成指定晶格頂點的隨機向量* @param x 橫向多少* @param y 縱向多少*/let cds = [];// CrystalDictsfunction loadCrystal(x, y) {if (cds[x] && cds[x][y]) {return cds[x][y]} else {if (!cds[x]) {cds[x] = [];}return cds[x][y] = {x: x,y: y,vector: {//晶格頂點的隨機,每次隨機后緩存x: mirror(Math.random() * 2, 0, 2, -1, 1),y: mirror(Math.random() * 2, 0, 2, -1, 1),}}}}//聲明畫板let el = document.getElementById('cv');let context = el.getContext("2d");//主函數function loadTwo() {let cel_num_x = 10,//橫向晶格數量cel_num_y = 10,//縱向晶格數量split = 10,//每個晶格繪制/插入 像素的數量pixel_size = 3,//實際像素繪制尺寸pixel_num_x = cel_num_x * split,//橫向像素總數pixel_num_y = cel_num_y * split;//縱向像素總數// 繪制像素點,橫縱像素點數量由晶格數量和每個晶格插值數量決定for (let i = 0; i < pixel_num_y; i++) {for (let j = 0; j < pixel_num_x; j++) {setTwoVal(j, i, pixel_size, split);}}}/*** 二維插值* @param x 像素的橫向位置索引* @param y 像素的縱向位置索引* @param size 像素實際繪制尺寸* @param split 一個晶格分為 split*split 個像素,用于計算像素相對晶格左上角的晶格單位偏移*/function setTwoVal(x, y, size, split) {//像素索引,即第幾列第幾行let pixel_x = x, pixel_y = y;// 計算晶體格的四周點,先計算左上角的晶體格的索引let loc_lt = {x: Math.floor(pixel_x / split), y: Math.floor(pixel_y / split)};let a0 = loadCrystal(loc_lt.x, loc_lt.y);let a1 = loadCrystal(loc_lt.x + 1, loc_lt.y);let a2 = loadCrystal(loc_lt.x, loc_lt.y + 1);let a3 = loadCrystal(loc_lt.x + 1, loc_lt.y + 1);//計算像素相對于所在晶格左上角偏移多少個晶格單位 => x,yx = Math.floor(x % split) / split;y = Math.floor(y % split) / split;//計算像素的晶格化坐標ox,oy//比如 像素p索引為 x:11 y:0 每個晶格分十個像素 則像素p的晶格坐標為1.1let ox = loc_lt.x + x;let oy = loc_lt.y + y;//計算像素權重,計算方法為:晶格四個頂點對像素影響權重的三次插值let fadeType = 0;//插值使用的平滑函數類型let val = lerp(lerp(dp({x: ox - a0.x, y: oy - a0.y}, a0.vector),dp({x: ox - a1.x, y: oy - a1.y}, a1.vector),x, fadeType),lerp(dp({x: ox - a2.x, y: oy - a2.y}, a2.vector),dp({x: ox - a3.x, y: oy - a3.y}, a3.vector),x, fadeType),y, fadeType);val = mirror(val, -1, 1, 0, 1);//繪制像素,注釋掉的為修改生成像素顏色,默認以透明度繪制// if(val > 150){// context.fillStyle = `rgb(186, 187, 183,${mirror(val,150,255,0.5,1)})`;// }// if(val>100&&val<=150){// context.fillStyle = `rgb(0, 210, 123,${mirror(val,100,150,0.5,1)})`;// }// if(val <=100){// context.fillStyle = `rgb(30, 132, 219,${mirror(val,0,100,0.5,1)})`;// }context.fillStyle = `rgb(0, 0, 0,${val})`;context.fillRect(pixel_x * size, pixel_y * size, size, size)}loadTwo(); </script> </body> </html>參考鏈接(參考資料使用python演示)
插值
一維柏林噪聲
二維柏林噪聲
總結
以上是生活随笔為你收集整理的柏林噪声双线性插值初步了解(js)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: afm原子力分析软件_牛津仪器发布全新大
- 下一篇: mnist数据集svm python_p