UI Menu Visual Glitch (Flickering) (Mandelbrot Fractal)

the reason i needed that spesific UI type is because it’s a part of a larger program i am working on to render different types of fractals and control them, the UI is dynamic and changes it’s sliders with each different fractal also see this if you have a creative idea …

this is my updated code with the ui fixed as some very basic color implementation

PGraphics pg; // Declare pg as a global variable
boolean rendering = false; // Declare rendering as a global variable
int activeSlider = -1; // Declare activeSlider as a global variable

// Mandelbrot specific parameters
float mandelbrotZoom = 1;
float mandelbrotOffsetX = 0;
float mandelbrotOffsetY = 0;
int mandelbrotIterations = 10; // Default to 10 iterations

void setup() {
  size(1920, 1080);
  pg = createGraphics(width, height); // Create a separate graphics buffer
}

void draw() {
  background(255); // Clear the main canvas

  synchronized (pg) {
    image(pg, 0, 0); // Draw the Mandelbrot fractal from the graphics buffer
  }

  drawUI(); // Draw the UI on top of everything else

  if (!rendering) {
    rendering = true;
    thread("renderMandelbrot");
  }
}

void renderMandelbrot() {
  PGraphics tempPg;
  synchronized (pg) {
    tempPg = createGraphics(pg.width, pg.height);
    tempPg.beginDraw();
    tempPg.colorMode(HSB, 360, 100, 100); // Set color mode to HSB (Hue, Saturation, Brightness)
    tempPg.background(0); // Set background to black
    tempPg.loadPixels();
    for (int x = 0; x < tempPg.width; x++) {
      for (int y = 0; y < tempPg.height; y++) {
        float a = map(x, 0, tempPg.width, -2.5 / mandelbrotZoom + mandelbrotOffsetX, 1 / mandelbrotZoom + mandelbrotOffsetX);
        float b = map(y, 0, tempPg.height, -1 / mandelbrotZoom + mandelbrotOffsetY, 1 / mandelbrotZoom + mandelbrotOffsetY);
        float ca = a;
        float cb = b;
        int n = 0;
        while (n < mandelbrotIterations) {
          float aa = a * a - b * b;
          float bb = 2 * a * b;
          a = aa + ca;
          b = bb + cb;
          if (abs(a + b) > 16) {
            break;
          }
          n++;
        }
        // Extended rainbow effect: map iterations to a wider range of hues
        float hue = map(n, 0, mandelbrotIterations, 0, 360); // Full spectrum of hues from 0 to 360
        float brightness = (n == mandelbrotIterations) ? 0 : 100; // Set brightness to 0 if max iterations reached
        tempPg.pixels[x + y * tempPg.width] = color(hue, 100, brightness);
      }
    }
    tempPg.updatePixels();
    tempPg.endDraw();
    pg = tempPg; // Update the main graphics buffer with the new rendering
  }

  rendering = false;
}

void drawUI() {
  // Draw the UI on the main canvas after the fractal is drawn
  fill(40, 255); // Set alpha to 255 for full opacity
  noStroke();
  rect(0, 0, 300, height);

  fill(255);
  textAlign(LEFT, CENTER);
  textSize(14);
  
  // Iterations slider
  fill(255);
  text("Iterations: " + mandelbrotIterations, 20, 30);
  fill(200);
  rect(20, 40, 260, 10, 5);
  fill(100);
  float iterKnobX = map(mandelbrotIterations, 1, 100, 20, 280);
  rect(iterKnobX - 5, 35, 10, 20, 5);
}

void mousePressed() {
  // Handling mouse interaction for Mandelbrot-specific sliders
  if (mouseX < 300) {
    if (mouseY > 25 && mouseY < 45) {
      activeSlider = 0; // Iterations slider
    }
  }
}

void mouseDragged() {
  // Update slider values based on dragging
  if (activeSlider == 0) {
    mandelbrotIterations = int(map(constrain(mouseX, 20, 280), 20, 280, 1, 100));
  }
}

void mouseReleased() {
  activeSlider = -1;
}

void mouseWheel(MouseEvent event) {
  // Handle zooming with the mouse wheel
  float e = event.getCount();
  float zoomFactor = 1.1;

  // Calculate the mouse position in world coordinates
  float mouseXWorld = map(mouseX, 0, width, -2.5 / mandelbrotZoom + mandelbrotOffsetX, 1 / mandelbrotZoom + mandelbrotOffsetX);
  float mouseYWorld = map(mouseY, 0, height, -1 / mandelbrotZoom + mandelbrotOffsetY, 1 / mandelbrotZoom + mandelbrotOffsetY);

  if (e < 0) {
    mandelbrotZoom *= zoomFactor;
  } else {
    mandelbrotZoom /= zoomFactor;
  }

  // Calculate the new mouse position in world coordinates after zooming
  float newMouseXWorld = map(mouseX, 0, width, -2.5 / mandelbrotZoom + mandelbrotOffsetX, 1 / mandelbrotZoom + mandelbrotOffsetX);
  float newMouseYWorld = map(mouseY, 0, height, -1 / mandelbrotZoom + mandelbrotOffsetY, 1 / mandelbrotZoom + mandelbrotOffsetY);

  // Adjust offsets to keep the zoom centered around the mouse
  mandelbrotOffsetX += mouseXWorld - newMouseXWorld;
  mandelbrotOffsetY += mouseYWorld - newMouseYWorld;
}

Updated with the ability to zoom in and some rainbow colors

3 Likes