Although I marked this as solved, I didn’t do much testing first. While the solution is alright, looping through each pixel is really power consuming and makes the sketch drop frames.
Which is why I wanted to improve it and use a limited area only to handle pixels.
I ended up creating an image using PGraphics and mask()
with a transparent circle in the middle (given some radius) and some extra area surrounding that circle, given the parameter again.
This is so that I can use pixels[]
array and check the alpha of each pixel only for this given image. If the pixel turns out to have alpha higher than 0, I deal with it.
In the end, the final result looks like this (background source):
I’m also using 4 black rectangles to fill the rest of the background with darkness. I really like the way this turned out!
Sketch code:
int radius = 75;
int black = radius * 5;
float d_multi = 1 / (float(radius)/100);
PImage img;
PImage mask;
PImage bg;
BGRect[] rects;
void setup() {
size(1380, 780, P2D);
bg = loadImage("bg.jpg");
bg.resize(width, height);
rects = new BGRect[] {
new BGRect(), new BGRect(), new BGRect(), new BGRect()
};
PGraphics pg = createGraphics(black, black);
pg.beginDraw();
pg.background(0, 0, 255); // Blue background does magic :)
pg.strokeWeight(2);
pg.stroke(255);
pg.translate(pg.width/2, pg.height/2);
pg.fill(0);
pg.circle(0, 0, radius*2);
pg.endDraw();
mask = pg.get();
pg.beginDraw();
pg.background(0, 0, 255);
pg.noStroke();
pg.translate(pg.width/2, pg.height/2);
pg.fill(0);
pg.rect(-pg.width/2, -pg.height/2, pg.width, pg.height);
pg.endDraw();
img = pg.copy();
pg.clear();
img.mask(mask);
}
void draw() {
background(170, 200, 100);
// Side rects:
rects[0].x = 0; rects[0].y = 0;
rects[0].w = mouseX - black/2; rects[0].h = height;
rects[1].x = mouseX + black/2; rects[1].y = 0;
rects[1].w = width - rects[1].x; rects[1].h = height;
// Top and down rects:
rects[2].x = mouseX - black/2; rects[2].y = 0;
rects[2].w = black; rects[2].h = mouseY - black/2;
rects[3].x = mouseX - black/2; rects[3].y = mouseY + black/2;
rects[3].w = black; rects[3].h = height - rects[3].y;
image(bg, 0, 0);
image(img, mouseX - black/2, mouseY - black/2);
img.loadPixels();
for(int x = 0; x < img.width; x++) {
for(int y = 0; y < img.height; y++) {
int loc = x + y * img.width;
float alpha = alpha(img.pixels[loc]);
float d = dist(mouseX, mouseY, mouseX - img.width/2 + x, mouseY - img.height/2 + y);
if(alpha > 0) {
float r = red(img.pixels[loc]);
float g = green(img.pixels[loc]);
float b = blue(img.pixels[loc]);
img.pixels[loc] = color(r, g, b, d * d_multi);
}
}
}
img.updatePixels();
for(int i = 0; i < rects.length; i++) {
rects[i].show();
}
}
void mouseWheel(MouseEvent e) {
if(e.getCount() == -1) {
if(d_multi > 1 / (float(radius)/100)) d_multi -= 0.05;
} else {
d_multi += 0.05;
}
}
…and BGRect
class:
class BGRect {
float x, y, w, h;
void show() {
pushMatrix();
noStroke();
fill(0);
rect(x, y, w, h);
popMatrix();
}
}