This is my Mandelbrot set program - it includes Smooth Coloring, perodicity checks, and my approach to biomorphs.
I know of Edge Detection, but I couldn't find a simple explanation that I can understand. Any help appreciated!
How do I optimize the Mandelbrot set plotting algorithm implemented in escapesmooth() and display() further?
#include <GL/glut.h>
#include <iostream>
#include <cmath>
float lerp(float a,float b,float t){return a+t*(b-a);}
const int WIDTH =800;
const int HEIGHT=600;
float r1,r2,g1,g2,b1,b2;
bool biomorph=false;
double xPos=-3.2;
double yPos=-2.0;
double zoom=150;
double startX,startY,start_X,start_Y;
int maxIter =50;
int maxIter2=50;
double zoomFactor=1.0;
float period=0;
bool render=true;
float escapesmooth(double real, double imag){ // Optimized Escape Time Algorithm + smooth colors + perodicity checks
    double r0=real;
    double i0=imag;
    float iter=0.0;
    double tempreal,io,ro;
    while(iter<maxIter&&real*real+imag*imag<=16){
        tempreal=real*real-imag*imag+r0;
        imag=2*real*imag+i0;
        real=tempreal;
        iter++;
        if(real==ro&&imag==io){
            iter=maxIter;
            break;
        }
        //interesting effect
        if(biomorph){
            if(abs(real)>0.75&&abs(imag)>0.75){
                iter=real+imag;
                break;
            }
        }
        period++;
        if(period>20){
            period=0;
            ro=real;
            io=imag;
        }
    }
    if(iter<maxIter){
        float log_zn=log((real*real)+(imag*imag))/2;
        float nu=log(log_zn/log(2))/log(2);
        iter=iter+1.0-nu;
    }
    return iter;
}
void display(){
    if(render){
        for(int x=0;x<WIDTH;x++){
            glBegin(GL_POINTS);
            for(int y=0;y<HEIGHT;y++){
                float iterations=escapesmooth(x/zoom+xPos,y/zoom+yPos);
                glVertex2i(x,y);
                if(iterations==maxIter){
                    glColor3f(0,0,0);
                }
                else{
                    float r1=0.5+sin(floor(iterations)/10)/2;
                    float g1=floor(iterations)/maxIter;
                    float b1=1-floor(iterations)/maxIter;
                    float r2=0.5+sin((floor(iterations)+1)/10)/2;
                    float g2=  (floor(iterations)+1)/maxIter;
                    float b2=1-(floor(iterations)+1)/maxIter;
                    /*Sunburst:*//*
                    float r1=floor(iterations)/32;
                    float r2=floor(iterations+1)/32;
                    float g1=floor(iterations)/64;
                    float g2=floor(iterations+1)/64;
                    float b1=floor(iterations)/128;
                    float b2=floor(iterations+1)/128;
                    /*test*//*
                    float r1=floor(iterations)/32;
                    float r2=floor(iterations+1)/32;
                    float g1=floor(iterations)/64;
                    float g2=floor(iterations+1)/64;
                    float b1=floor(iterations)/128;
                    float b2=floor(iterations+1)/128;*/
                    float t=fmod(iterations,1);
                    glColor3f(lerp(r1,r2,t),lerp(g1,g2,t),lerp(b1,b2,t));
                }
            }
            glEnd();
            glFlush();}
        }
    //maxIter*=1.2;
}
void reshape(int w,int h){glutReshapeWindow(WIDTH,HEIGHT);}
bool isDragging = false;
int lastX,lastY;
void mouse(int button, int state, int x, int y){
    double mouseX=static_cast<double>(x)/WIDTH;
    double mouseY=static_cast<double>(y)/HEIGHT;
    if(button==GLUT_LEFT_BUTTON&&state==GLUT_DOWN){
        isDragging=true;
        lastX=x;
        lastY=y;
    } else if(button==GLUT_LEFT_BUTTON&&state==GLUT_UP){
        isDragging=false;
    }
}
void motion(int x, int y) {
    if (isDragging) {
        double deltaX=(x-lastX)/zoom;
        double deltaY=(y-lastY)/zoom;
        xPos-=deltaX;
        yPos+=deltaY;
        lastX=x;
        lastY=y;
        maxIter=maxIter2;
        glutPostRedisplay();
    }
}
void key(unsigned char key, int x, int y) {
    switch (key){
    case 'q': {
        zoom *= 1.1;
        maxIter = maxIter2;
        render = true;
        glutPostRedisplay();
        break;
    }
    case 'e': {
        zoom *= 0.9;
        maxIter = maxIter2;
        render = true;
        glutPostRedisplay();
        break;
    }
        case '=': {maxIter2 += 1;maxIter = maxIter2;render = true;glutPostRedisplay();break;}
        case '+': {maxIter2 += 1;maxIter = maxIter2;render = true;glutPostRedisplay();break;}
        case '-': {maxIter2 -= 1;maxIter = maxIter2;render = true;glutPostRedisplay();break;}
        case 'b': {if(biomorph){biomorph=false;}else{biomorph=true;}glutPostRedisplay();break;}
        case 'r': {double xPos=-3.2;double yPos=-2.0;double zoom=150;maxIter = 50;render = true;glutPostRedisplay();break;}
    }
}
int main(int argc, char** argv){
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowSize(WIDTH,HEIGHT);
    glutCreateWindow("mandel badandel");
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D(0, WIDTH, 0, HEIGHT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glClearColor(0.0,0.0,0.0,1.0);
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutMouseFunc(mouse);
    glutMotionFunc(motion);
    glutKeyboardFunc(key);
    glutMainLoop();
    return 0;
}


