amnon.owed's algorithm yields 43fps on my computer.
I rewrote it a little bit and now obtain between 53 and 55 fps. Actually, it just calculates the regions of interest, not the whole canvas.
Amnon.owed's algorithm uses about 844000 loop runs (4 circles with a total of 150*150*PI pixels = 282735 pixels times 2.5 distance checks on average, plus (700*600 - 282735) times 4 distance checks).
My algorithm uses 720000 loop runs (4 * 300 * 300 with distance checks and 4 * 300 * 300 for resetting the color) in the worst case, when all rings are completely within the canvas.
With regards to the question that was not asked, blurring: One can use color(0, distance / visibilityRadius) (or the squared distance/radius) instead of 0x00FFFFF. I would then recommend, however, to use amnon.owed's algorithm, since mine does not include "collision detection" and hence would yield Moiré effets.
- PImage img, fog;
- color black = color(0, 125);
- PVector[] vecs = new PVector[4]; // don't create PVectors in the draw loop
- int visibilityRadius = 150;
- int visibilityRadius2 = visibilityRadius * visibilityRadius; // for use with fast 2d distance function
-
- void setup() {
- size(700, 600);
- img = loadImage("http://www.salepaintings.com/uploads/4/1/9/7/4197246/8232646_orig.jpg");
- // img = loadImage("8232646_orig.jpg");
- fog = createImage(width, height, ARGB); // don't create fog image in the draw loop
- fog.loadPixels();
- for (int i=0, y=0; y<fog.height; y++) {
- for (int x=0; x<fog.width; x++, i++) {
- fog.pixels[i] = black;
- }
- }
- fog.updatePixels();
-
- for (int i=0; i<vecs.length; i++) {
- vecs[i] = new PVector();
- }
- }
-
- void draw() {
- background(img);
- vecs[0].set(mouseX, mouseY, 0); // hero 1
- vecs[1].set(width-mouseX, height-mouseY, 0); // hero 2
- vecs[2].set(frameCount % width,140,0); // hero 3
- vecs[3].set(500,frameCount%height,0); // hero 4
- drawFog(vecs);
- println(int(frameRate)); // runs at 59 fps for me
- }
-
- void drawFog(PVector[] vecs) {
- fog.loadPixels();
- for (int i=0; i<vecs.length; i++) {
- float vec_x = vecs[i].x;
- float vec_y = vecs[i].y;
- int v_left = int(vec_x - visibilityRadius);
- int v_right = int(vec_x + visibilityRadius);
- int v_top = int(vec_y - visibilityRadius);
- int v_bottom = int(vec_y + visibilityRadius);
-
- int x_start = max(0,v_left);
- int x_end = min(width,v_right);
- int y_start=max(0,v_top);
- int y_end=min(height,v_bottom);
-
- for (int y = y_start; y < y_end; y++) {
- for (int x = x_start; x < x_end; x++) {
- int j = y * width + x;
- if (d(vec_x, vec_y, x, y) < visibilityRadius2) {
- fog.pixels[j] &= 0x00FFFFFF;
- }
- }
- }
- }
-
-
- fog.updatePixels();
- image(fog,0,0);
- fog.loadPixels();
-
- for (int i=0; i<vecs.length; i++) {
- float vec_x = vecs[i].x;
- float vec_y = vecs[i].y;
- int v_left = int(vec_x - visibilityRadius);
- int v_right = int(vec_x + visibilityRadius);
- int v_top = int(vec_y - visibilityRadius);
- int v_bottom = int(vec_y + visibilityRadius);
-
- int x_start = max(0,v_left);
- int x_end = min(width,v_right);
- int y_start=max(0,v_top);
- int y_end=min(height,v_bottom);
-
- for (int y=y_start; y < y_end; y++) {
- for (int x=x_start; x < x_end; x++) {
- int j = y * width + x;
- fog.pixels[j] = black;
- }
- }
- }
- fog.updatePixels();
- }
-
-
- float d( float x1, float y1, float x2, float y2) {
- return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
- }