I created a simple perlin noise generator using p5.js, which is based on this link . For the most part, I got 80% of the algorithm working. The only issue is that there is defined discontinuities aligned with each gradient vector. the code for this project is shown below.
// noprotect
var screen_width = 400;
var screen_height = 400;
var res = 2;
var gvecs = {};
function setup() {
createCanvas(screen_width, screen_height);
initialize_gvecs();
draw_perlin_noise();
}
function draw() {
console.log(gvecs);
noLoop();
}
function initialize_gvecs() {
for (var y = 0; y <= res; y ) {
for (var x = 0; x <= res; x ) {
let theta = Math.random() * 2 * Math.PI;
gvecs[[x, y]] = {
x: Math.cos(theta),
y: Math.sin(theta)
};
}
}
}
function draw_perlin_noise() {
loadPixels();
for (var y = 0; y < screen_height; y ) {
for (var x = 0; x < screen_width; x ) {
var world_coordx = map(x, 0, screen_width, 0, res);
var world_coordy = map(y, 0, screen_height, 0, res);
var top_L_x = Math.floor(world_coordx);
var top_L_y = Math.floor(world_coordy);
var top_R_x = top_L_x 1;
var top_R_y = top_L_y;
var bottom_L_x = top_L_x;
var bottom_L_y = top_L_y 1;
var bottom_R_x = top_L_x 1;
var bottom_R_y = top_L_y 1;
var top_L_g = gvecs[[top_L_x, top_L_y]];
var top_R_g = gvecs[[top_R_x, top_R_y]];
var bottom_L_g = gvecs[[bottom_L_x, bottom_L_y]];
var bottom_R_g = gvecs[[bottom_R_x, bottom_R_y]];
var btw_top_L = {
x: world_coordx - top_L_x,
y: world_coordy - top_L_y
};
var btw_top_R = {
x: world_coordx - top_R_x,
y: world_coordy - top_R_y
};
var btw_bottom_L = {
x: world_coordx - bottom_L_x,
y: world_coordy - bottom_L_y
};
var btw_bottom_R = {
x: world_coordx - bottom_R_x,
y: world_coordy - bottom_R_y
};
var v = top_L_g.x * btw_top_L.x top_L_g.y * btw_top_L.y;
var u = top_R_g.x * btw_top_R.x top_R_g.y * btw_top_R.y;
var s = bottom_L_g.x * btw_bottom_L.x bottom_L_g.y * btw_bottom_L.y;
var t = bottom_R_g.x * btw_bottom_R.x bottom_R_g.y * btw_bottom_R.y;
var Sx = ease_curve(world_coordx - top_L_x);
var a = s Sx * (t - s);
var b = u Sx * (v - u);
var Sy = ease_curve(world_coordy - top_L_y);
var final_val = a Sy * (b - a);
pixels[(x y * screen_width) * 4] = map(final_val, -1, 1, 0, 255);
pixels[(x y * screen_width) * 4 1] = map(final_val, -1, 1, 0, 255);
pixels[(x y * screen_width) * 4 2] = map(final_val, -1, 1, 0, 255);
pixels[(x y * screen_width) * 4 3] = 255;
}
}
updatePixels();
}
function ease_curve(x) {
return 6 * x ** 5 - 15 * x ** 4 10 * x ** 3;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js"></script>
an image of the issue I'm having is shown below.
I suspect that my issue has to do with the value between each gradient vector not properly using the adjacent gradient vectors, but I've tested and debugged this extensively and I cant find the issue. I've also tried several different ease_curve functions, but none of them seem to change anything. Any help would be greatly appreciated.
CodePudding user response:
Bilinear interpolation might be twisted.
var Sx = ease_curve(world_coordx - top_L_x);
var a = s Sx * (t - s);
//var b = u Sx * (v - u);
var b = v Sx * (u - v);
var Sy = ease_curve(world_coordy - top_L_y);
//var final_val = a Sy * (b - a);
var final_val = b Sy * (a - b);