Skip to content

Instantly share code, notes, and snippets.

@attic-stuff
Last active April 12, 2025 21:06
Show Gist options
  • Select an option

  • Save attic-stuff/ab907b28dde0f5dba6a5b70e47e0780c to your computer and use it in GitHub Desktop.

Select an option

Save attic-stuff/ab907b28dde0f5dba6a5b70e47e0780c to your computer and use it in GitHub Desktop.
generate an array of points using a blue noise distribution.
/**
* generates an array of blue noise points using poisson discs
* @param {real} width the width of the region of points
* @param {real} height the height of the region of points
* @param {real} radius the poisson disc radius, or space between each point
* @param {real} rejections the number of attempts made to generate a point before moving on
*/
function bluenoise(width, height, radius = 4, rejections = 30) constructor {
static sample = function(x, y) constructor {
self.x = x;
self.y = y;
static draw = function(c) {
draw_point_color(x, y, c);
}
}
cell = radius / sqrt(2);
columns = ceil(width / cell);
rows = ceil(height / cell);
noise = array_create(columns * rows, noone);
self.rejections = rejections;
self.width = width;
self.height = height;
self.radius = radius;
var point = new sample(random(width), random(height));
list = [point];
noise[floor(point.x / cell) + floor(point.y / cell) * columns] = point;
//if you want to generate all points at one do like
// while (array_length(noise.list) > 0) {
// noise.step(1);
// }
static step = function(n) {
repeat (n) {
if (array_length(list) > 0) {
var i = irandom(array_length(list) - 1);
var index = list[i];
var valid = false;
repeat (rejections) {
var dir = irandom(360);
var length = radius + irandom(radius);
var px = index.x + lengthdir_x(length, dir);
var py = index.y + lengthdir_y(length, dir);
if (point_in_rectangle(px, py, 0, 0, width, height) == false) {
break;
}
var point = new sample(px, py);
var column = floor(px / cell);
var row = floor(py / cell);
var check = true;
for (var j = -2; j < 3; j++) {
if (check == false) {
break;
}
for (var k = -2; k < 3; k++) {
var c = column + j;
var r = row + k;
if (point_in_rectangle(c, r, 0, 0, columns - 1, rows - 1) == true) {
var neighbor = noise[c + r * columns];
if (neighbor != noone) {
if (point_distance(px, py, neighbor.x, neighbor.y) < radius) {
check = false;
break;
}
}
}
}
}
if (check == true) {
noise[column + row * columns] = point;
array_push(list, point);
valid = true;
break;
}
}
if (valid == false) {
array_delete(list, i, 1);
}
} else {
return false;
}
}
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment