hi, i started to study opengl few days ago, and i wanted to try to draw a mandelbrot set (the fractal by definition) in 2d using opengl/glut
the problem i get is that everything i obtain is a black window
here i post the code (very simple):
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdio.h>
#define W 640
#define H 480
#define Xmin -2.0
#define Xmax 2.0
#define Ymin -2.0
#define Ymax 2.0
#define STEP 0.005
#define ITERS 512
typedef struct _complex
{
double r, i;
}Complex;
void reshape(int w, int h)
{
//rende l'intera area visibile
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
//impostano il sistema di coordinate
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D((GLdouble)0, (GLdouble) W, (GLdouble)0, (GLdouble) H);
}
void display(void)
{
Complex c, z_n;
int x, y, n;
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POINTS);
glColor3d((GLdouble) 1.0, (GLdouble) 1.0, (GLdouble) 1.0);
//creazione frattale
for(x = 0; x < W; x++)
{
z_n.r = c.r = (x / W) * (Xmax - Xmin) + Xmin; //calcolo c.r solo quando cambia
for(y = 0; y < H; y++)
{
z_n.i = c.i = (y / H) * (Ymax - Ymin) + Ymin;
//inizio del ciclo di iterazioni per scoprire se la funzione iterata converge o meno
for(n = 0; n < ITERS; n++)
{
if((((z_n.r * z_n.r) + (z_n.i * z_n.i))) > 4.0)
{
glVertex2i(x, y);
break;
}
//else
z_n.r = (z_n.r * z_n.r) - (z_n.i * z_n.i) + c.r;
z_n.i = (2 * z_n.r * z_n.i) + c.i;
}
}
}
glEnd();
glFlush();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glClearColor(0.0, 0.0, 0.0, 0.0);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(W, H);
glutCreateWindow("glFractal");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutMainLoop();
return 0;
}
i would really appreciate if someone can help me in these first steps in the world of opengl
bye
Your coordinates are screen coordinates. The coordinate system uses values from -1.0 to 1.0. So your are rendering outside the screen I guess. Use float or double as coordinates and have the values range from -1.0 to 1.0.
512 iteration O_O it will take forever…
Here the corrected code.
Complex temp, z_n, c;
float scale = 0.005f; // 200 pixel un unita'
float xLimit = (winWidth_*0.5f)*scale;
float yLimit = (winHeight_*0.5f)*scale;
if(viewportNeedUpdate_){
// you can move this part in your resize function
glLoadIdentity();
glOrtho(-xLimit, xLimit, -yLimit, yLimit, -1, 1);
}
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POINTS);
//creazione frattale
for(float x = -xLimit; x < xLimit; x += scale)
{
for(float y = -yLimit; y < yLimit; y+= scale)
{
z_n.r = .0f;
z_n.i = .0f;
c.r = x;
c.i = y;
for(unsigned int n = 0; n < 50; n++)
{
if((((z_n.r * z_n.r) + (z_n.i * z_n.i))) > 4.0)
{
glColor3f(n*0.02f, 0.02f, 0.02f);
glVertex2f(x, y);
break;
}
temp.r = (z_n.r * z_n.r) - (z_n.i * z_n.i) + c.r;
temp.i = (2 * z_n.r * z_n.i) + c.i;
z_n.r = temp.r;
z_n.i = temp.i;
}
}
}
glEnd();
Here the corrected code, I modified a little bit your application
First, the computation of the orbit was wrong.
The right computation is
Z = 0 (not c)
Z_n+1 = z_n^2 + c
You need to use a temp variable or you are computing the wrong value.
Also you can change color per pixel based on the number of iteration. It give a better effect.
I modified also the work area, now there is a scale factor (200 pixel = 1 unit) so the curve is not distorted and you can resize the windows without problem.
In Italian (sorry guys, only basic openGL hints):
Ho modificato un po’ la parte di disegno, il resto è solo glut standard ed era giusto.
A proposito, openGl non è fatto apposta per fare questo tipo di programma. openGL è organizzato per renderizzare triangoli e possibilmente far fare tutto il lavoro alla scheda video. In pratica così la tua applicazione fa tutti i calcoli sulla CPU e manda un vertice ogni morte di papa alla scheda video (che lo processa in un picosecondo). Prova a rifare la stessa cosa dentro uno shader, vedrai che andrà cento volte più veloce.
hi rosario, thanks very much for your tips.
the main problem was the lack of a temp complex variable. the program will work just adding it. but with this other corrections it goes better.
regarding the initialization of the variable z_n, both are right, because if z_n = 0, in the first iteration it’ll become z_n = c. in practice i skip an iteration, but that’s not the point…
i know that all the computations are made by the cpu, i guess with a shader this work will be done by the gpu, am i right?
when i read something about the shaders, i will try it.