martedì 26 febbraio 2013

Mandelbrot in OpenGL su Linux/Debian

In questo post viene presentato un programma per creare l'insieme di Mandelbrot in OpenGL.
Questa specifica permette di scrivere codice astraendosi dai differenti acceleratori grafici con API uniformi tra le varie piattaforme in cui e' implementata OpenGL ed e' necessario avere una scheda grafica abilitata per poter funzionare

In Debian, per programmare in OpenGL, si deve installare FreeGlut (Glut e' una estensione ad OpenGL che permette di gestire la creazione delle finestre e gli eventi da tastiera anche questa indipendente tra varie piattaforme)

apt-get install freeglut3-dev


Mandelbrot in OpenGL


Per compilare il codice sottostante si usa la seguente stringa

g++ -Wall -O3 mandel.cpp -o mandel -lglut -lGLU

il codice utilizzato e' sempre quello di base gia' presentato nei precedenti esempi e sono evidenziate in giallo le direttive tipiche di OpenGL
Si deve evidenziare che in questo caso viene utilizzato un Double Buffering RGB
La cosa curiosa utilizzando OpenGL (rispetto all'esperienza con altre librerie) e' il modo di mappare i pixel
In pratica il numero di pixel non e' per definizione quella massima della finestra creata ma deve essere esplicitamente definito da gluOrtho2D(0.0,640.0,0.0,480.0);
Nel caso in cui non si glVertex2i (che accetta come input coordinate intere) ma glVertex2f (coordinate float) lo spazio delle coordinate e' compreso tra -1.0 e 1.0
--------------------------------------------------
#include <GL/gl.h>
#include <GL/glut.h>

#include <stdio.h>

#define SCREEN_WIDTH 640
#define SCREEN_HEIGHT 480


float re_min = -2.0;
float im_min = -1.2;

float re_max = 1.0;
float im_max = 1.2;

int iterazioni = 1024;


float a,b;
float x,y,x_new,y_new;

int test;

int k,j,i;
 

void disegna()
{

    float re_factor = (re_max-re_min);
    float im_factor = (im_max-im_min);
   
    glColor3f(1, 1, 1);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();


    glClear(GL_COLOR_BUFFER_BIT);
    glBegin (GL_POINTS);


    for (i=0;i<SCREEN_HEIGHT;i++)
     {
     for (j=0;j<SCREEN_WIDTH;j++)
      {
      a = re_min+(j*re_factor/SCREEN_WIDTH);
      b = im_min+(i*im_factor/SCREEN_HEIGHT);
     
      x = 0;
      y = 0;
      test = 0;
     
      for (k=0;k<iterazioni;k++)
       {
       x_new = (x*x)-(y*y)+a;
       y_new = (2*x*y)+b;
       if (((x_new*x_new)+(y_new*y_new))>4)
        {
        test = k;
        if (k%2 == 0) glVertex2i(j,i);        

        break;
        }
       x = x_new;
       y = y_new;
       }
            
      }
   
     }
    glEnd();            

    glutSwapBuffers();   
}

int main(int argc, char* argv[])
{
    glutInit (&argc, argv);
    glutInitDisplayMode (GLUT_RGB|GLUT_DOUBLE);
    glutInitWindowSize(SCREEN_WIDTH, SCREEN_HEIGHT);
    glutInitWindowPosition(0, 0);
    glutCreateWindow("Mandelbrot");
    gluOrtho2D(0.0,640.0,0.0,480.0);
    glutDisplayFunc(disegna);
    glutMainLoop();

    return 0;
}