How does one zoom into the project and pan it in GL/Glut

Well i’ve got this simple Mandelbrot set and i wonder how does one zoom into the object and pan the view?
Mandelbrot.h

void Mandelbrot(int maxiter){
	double left=-2.0;
	double right=1.0;
	double top=1.125;
	double bottom=-1.125;

	const int width = glutGet( GLUT_WINDOW_WIDTH );
	const int height = glutGet( GLUT_WINDOW_HEIGHT );

	glBegin( GL_POINTS );
	for(int y=0; y<height; ++y)
	{
		for(int x=0; x<width; ++x)
		{
			complex<double> c( left + ( x * ( right - left ) / width ),
			                top + ( y * ( bottom - top ) / height ) );

			complex<double> z ( 0.0,0.0 );

			int iteration = 0;

			while( abs( z ) < 2.0 && maxiter > iteration){

				z = ( z * z ) + c;

				++iteration;

			}
            if( iteration < maxiter )
            {
                glColor3f( 0.0, 1.0, 0.0 );
                glVertex2i( x, y  );
            }
            else
            {
                glColor3f( 0.0, 0.0, 0.0 );
                glVertex2i( x, y );
            }
		}
	}
	glEnd();
}

main.cpp


void display(){
	glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
	    glClear( GL_COLOR_BUFFER_BIT );

	    glMatrixMode( GL_PROJECTION );
	    glLoadIdentity();
	    const int width = glutGet( GLUT_WINDOW_WIDTH );
	    const int height = glutGet( GLUT_WINDOW_HEIGHT );
	    glOrtho( 0, width, 0, height, -1, 1 );

	    glMatrixMode( GL_MODELVIEW );
	    glLoadIdentity();

	    Mandelbrot(maxiter);
	    glutSwapBuffers();
}

void Keyboard(unsigned char key,int x,int y){
	switch(key){
	case '[':
		maxiter--;
		glutPostRedisplay();
		break;
	case ']':
		maxiter++;
		glutPostRedisplay();
		break;
	}
}

int main( int argc, char** argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB );
    glutCreateWindow( "Mandelbrot" );
    glutReshapeWindow( 400,400 );
    glutDisplayFunc( display );
    glutKeyboardFunc(Keyboard);
    glutMainLoop();
    return 0;
}

Btw i got skeleton of Mandelbrot set from a thread.
And everything in this code is subject to change.
Maybe even it’s impossible with GL/glut.h and i will need download other extensions for OpenGL ?

Oh and sorry for accidental double post.

I see you’ve chosen to use the old Fixed-Function pipeline. Just letting you know this would have been WAY easier with shaders… In fact I rendered my very first mandelbrot set with GLSL

My vertex shader:

#version 330

layout( location = 0 ) in vec3 vPosition;

out vec2 texcoord;

vec3 worldpos; //Position of the fragment in the world!

uniform mat4 World2Camera; //the world to camera transform. I figure this is faster than calculating MVP seperately per vertex.
void
main()
{
	vec4 newpos = World2Camera * vec4(vPosition,1.0);
	gl_Position = newpos;
	texcoord.x = (newpos.x + 1.0)*0.5;
	texcoord.y = (newpos.y + 1.0)*0.5;
}

and my highly unoptimized fragment shader which actually does the mandelbrot set:


#version 330
//out vec4 fColor[2];

in vec2 texcoord; // 0 to 1 in both directions
int iter = 50;

uniform sampler2D diffuse; //This is actually the texture unit. limit 32. This one happens to be for the literal object's texture.

vec2 mandelbrotcoords;
vec4 colors[5];
float numcolors = 5.0;
int numcolors_int = 5;

//f(z) = z^2+C does not diverge as you call it on itself eg f(f(f(z)));

//Mandelbrot code
	int mandelbrot_test(vec2 c, int maxiter, float testvalsq) { //x component is real, y is imaginary
		float zr = 0;
		float zi = 0; //Factor of i
		float lastzr = 0;
		for (int i = 0; i < maxiter; i++)
		{
			zr = (zr * zr) - (zi * zi) + c.x;
			zi = 2 * lastzr * zi + c.y;
			if(zr * zr + zi * zi > testvalsq){
				return i;
			}
			lastzr = zr;
		}
		return maxiter;
	}
	vec2 centeraroundpointonmandelbrot(vec2 locationonscreen, vec2 centerinmandelspace,vec2 range){
		//Take the location on the screen which is from 0 to 1 in x and y, and move the center, 0.5,0.5 to the centerinmandelspace. We want to scale the the coordinates relative to it 
		vec2 result;
		//Move to origin
		result.x = locationonscreen.x -0.5;
		result.y = locationonscreen.y -0.5;
		//Scale
		result.x = result.x * range.x;
		result.y = result.y * range.y;
		//Move to center of mandelbrotspace
		result.x = result.x + centerinmandelspace.x;
		result.y = result.y + centerinmandelspace.y;
		return result;
	}
vec4 lerpColor(float input){
	// float numcolors = 5.0;
	// int numcolors_int = 5;
	// distance between each colors is equal
	// We want to find the one above and the one below the input
	vec4 color1 = vec4(0,0,0,0);
	vec4 color2 = vec4(0,0,0,0);
	float somethin = 0;
	float point = input * (numcolors-1);
	if (point == float(int(point)))
	{
		return colors[int(point)];
	}
	color1 = colors[int(point)];
	color2 = colors[1+int(point)];
	somethin = point - float(int(point));
	return mix(color1, color2, input);
}


void main()
{
	//setup colors
	colors[0] = vec4(0.0, 6.0/255.0, 43.0/255.0, 0.0);
	colors[1] = vec4(140.0/255.0, 153.0/255.0, 0.0/255.0, 0.0);
	colors[2] = vec4(252.0/255.0, 194.0/255.0, 0.0/255.0, 0.0);
	colors[3] = vec4(25.0/255.0, 252.0/255.0, 0.0/255.0, 0.0);
	colors[4] = vec4(0.0, 0.0, 255.0, 0.0);
	mandelbrotcoords = centeraroundpointonmandelbrot(texcoord, vec2(-0.5,0.0), vec2(3.0,2.0));
	float mandelresult = float(mandelbrot_test(mandelbrotcoords, 255, 1000.0))/255.0;
	gl_FragColor = lerpColor(mandelresult);
	//gl_FragColor = texture2D(diffuse, texcoord);
	
}

THAT ASIDE…

You can use GLU, glPushMatrix() and glPopMatrix() to do simple transforms if that is what you want to do

but I highly suggest you move to the modern pipeline

I see you’ve chosen to use the old Fixed-Function pipeline. Just letting you know this would have been WAY easier with shaders… In fact I rendered my very first mandelbrot set with GLSL

My vertex shader:
Code :

#version 330

layout( location = 0 ) in vec3 vPosition;

out vec2 texcoord;

vec3 worldpos; //Position of the fragment in the world!

uniform mat4 World2Camera; //the world to camera transform. I figure this is faster than calculating MVP seperately per vertex.
void
main()
{
vec4 newpos = World2Camera * vec4(vPosition,1.0);
gl_Position = newpos;
texcoord.x = (newpos.x + 1.0)*0.5;
texcoord.y = (newpos.y + 1.0)*0.5;
}

and my highly unoptimized fragment shader which actually does the mandelbrot set:

#version 330
//out vec4 fColor[2];

in vec2 texcoord; // 0 to 1 in both directions
int iter = 50;

uniform sampler2D diffuse; //This is actually the texture unit. limit 32. This one happens to be for the literal object’s texture.

vec2 mandelbrotcoords;
vec4 colors[5];
float numcolors = 5.0;
int numcolors_int = 5;

//f(z) = z^2+C does not diverge as you call it on itself eg f(f(f(z)));

//Mandelbrot code
int mandelbrot_test(vec2 c, int maxiter, float testvalsq) { //x component is real, y is imaginary
float zr = 0;
float zi = 0; //Factor of i
float lastzr = 0;
for (int i = 0; i < maxiter; i++)
{
zr = (zr * zr) - (zi * zi) + c.x;
zi = 2 * lastzr * zi + c.y;
if(zr * zr + zi * zi > testvalsq){
return i;
}
lastzr = zr;
}
return maxiter;
}
vec2 centeraroundpointonmandelbrot(vec2 locationonscreen, vec2 centerinmandelspace,vec2 range){
//Take the location on the screen which is from 0 to 1 in x and y, and move the center, 0.5,0.5 to the centerinmandelspace. We want to scale the the coordinates relative to it
vec2 result;
//Move to origin
result.x = locationonscreen.x -0.5;
result.y = locationonscreen.y -0.5;
//Scale
result.x = result.x * range.x;
result.y = result.y * range.y;
//Move to center of mandelbrotspace
result.x = result.x + centerinmandelspace.x;
result.y = result.y + centerinmandelspace.y;
return result;
}
vec4 lerpColor(float input){
// float numcolors = 5.0;
// int numcolors_int = 5;
// distance between each colors is equal
// We want to find the one above and the one below the input
vec4 color1 = vec4(0,0,0,0);
vec4 color2 = vec4(0,0,0,0);
float somethin = 0;
float point = input * (numcolors-1);
if (point == float(int(point)))
{
return colors[int(point)];
}
color1 = colors[int(point)];
color2 = colors[1+int(point)];
somethin = point - float(int(point));
return mix(color1, color2, input);
}

void main()
{
//setup colors
colors[0] = vec4(0.0, 6.0/255.0, 43.0/255.0, 0.0);
colors[1] = vec4(140.0/255.0, 153.0/255.0, 0.0/255.0, 0.0);
colors[2] = vec4(252.0/255.0, 194.0/255.0, 0.0/255.0, 0.0);
colors[3] = vec4(25.0/255.0, 252.0/255.0, 0.0/255.0, 0.0);
colors[4] = vec4(0.0, 0.0, 255.0, 0.0);
mandelbrotcoords = centeraroundpointonmandelbrot(texcoord, vec2(-0.5,0.0), vec2(3.0,2.0));
float mandelresult = float(mandelbrot_test(mandelbrotcoords, 255, 1000.0))/255.0;
gl_FragColor = lerpColor(mandelresult);
//gl_FragColor = texture2D(diffuse, texcoord);

}

THAT ASIDE…

You can use GLU, glPushMatrix() and glPopMatrix() to do simple transforms if that is what you want to do

but I highly suggest you move to the modern pipeline

Well then… i should relearn OpenGL as i tought.
Main problem for me that eclipse Oxygen with MINGW compiler does not recognize GLSL or even GLEW.

[QUOTE=StabberKnight906;1291223]
Main problem for me that eclipse Oxygen with MINGW compiler does not recognize GLSL or even GLEW.[/QUOTE]
GLSL doesn’t require any interaction with the development environment. The GLSL compiler and linker are part of the OpenGL implementation (GLSL code is compiled and linked using OpenGL functions within the program).

If you’re having issues with GLEW, you don’t need to build it as a separate library. You can define GLEW_STATIC and just add glew.c to the project as a source file.

[QUOTE=Geklmin;1291214]I see you’ve chosen to use the old Fixed-Function pipeline. Just letting you know this would have been WAY easier with shaders… In fact I rendered my very first mandelbrot set with GLSL

My vertex shader:

#version 330

layout( location = 0 ) in vec3 vPosition;

out vec2 texcoord;

vec3 worldpos; //Position of the fragment in the world!

uniform mat4 World2Camera; //the world to camera transform. I figure this is faster than calculating MVP seperately per vertex.
void
main()
{
	vec4 newpos = World2Camera * vec4(vPosition,1.0);
	gl_Position = newpos;
	texcoord.x = (newpos.x + 1.0)*0.5;
	texcoord.y = (newpos.y + 1.0)*0.5;
}

and my highly unoptimized fragment shader which actually does the mandelbrot set:


#version 330
//out vec4 fColor[2];

in vec2 texcoord; // 0 to 1 in both directions
int iter = 50;

uniform sampler2D diffuse; //This is actually the texture unit. limit 32. This one happens to be for the literal object's texture.

vec2 mandelbrotcoords;
vec4 colors[5];
float numcolors = 5.0;
int numcolors_int = 5;

//f(z) = z^2+C does not diverge as you call it on itself eg f(f(f(z)));

//Mandelbrot code
	int mandelbrot_test(vec2 c, int maxiter, float testvalsq) { //x component is real, y is imaginary
		float zr = 0;
		float zi = 0; //Factor of i
		float lastzr = 0;
		for (int i = 0; i < maxiter; i++)
		{
			zr = (zr * zr) - (zi * zi) + c.x;
			zi = 2 * lastzr * zi + c.y;
			if(zr * zr + zi * zi > testvalsq){
				return i;
			}
			lastzr = zr;
		}
		return maxiter;
	}
	vec2 centeraroundpointonmandelbrot(vec2 locationonscreen, vec2 centerinmandelspace,vec2 range){
		//Take the location on the screen which is from 0 to 1 in x and y, and move the center, 0.5,0.5 to the centerinmandelspace. We want to scale the the coordinates relative to it 
		vec2 result;
		//Move to origin
		result.x = locationonscreen.x -0.5;
		result.y = locationonscreen.y -0.5;
		//Scale
		result.x = result.x * range.x;
		result.y = result.y * range.y;
		//Move to center of mandelbrotspace
		result.x = result.x + centerinmandelspace.x;
		result.y = result.y + centerinmandelspace.y;
		return result;
	}
vec4 lerpColor(float input){
	// float numcolors = 5.0;
	// int numcolors_int = 5;
	// distance between each colors is equal
	// We want to find the one above and the one below the input
	vec4 color1 = vec4(0,0,0,0);
	vec4 color2 = vec4(0,0,0,0);
	float somethin = 0;
	float point = input * (numcolors-1);
	if (point == float(int(point)))
	{
		return colors[int(point)];
	}
	color1 = colors[int(point)];
	color2 = colors[1+int(point)];
	somethin = point - float(int(point));
	return mix(color1, color2, input);
}


void main()
{
	//setup colors
	colors[0] = vec4(0.0, 6.0/255.0, 43.0/255.0, 0.0);
	colors[1] = vec4(140.0/255.0, 153.0/255.0, 0.0/255.0, 0.0);
	colors[2] = vec4(252.0/255.0, 194.0/255.0, 0.0/255.0, 0.0);
	colors[3] = vec4(25.0/255.0, 252.0/255.0, 0.0/255.0, 0.0);
	colors[4] = vec4(0.0, 0.0, 255.0, 0.0);
	mandelbrotcoords = centeraroundpointonmandelbrot(texcoord, vec2(-0.5,0.0), vec2(3.0,2.0));
	float mandelresult = float(mandelbrot_test(mandelbrotcoords, 255, 1000.0))/255.0;
	gl_FragColor = lerpColor(mandelresult);
	//gl_FragColor = texture2D(diffuse, texcoord);
	
}

THAT ASIDE…

You can use GLU, glPushMatrix() and glPopMatrix() to do simple transforms if that is what you want to do

but I highly suggest you move to the modern pipeline[/QUOTE]

And may i ask you a question ?

Will vertex shader, be responsible for zooming and panning or zoom and pan would go into main.c/cpp ?

Edit:
Now im remaking mandelbrot in GL/GLEW.h with GLSL.