If you render a triangle and then use glScale to zoom as is suggested by some, OpenGL is still rendering the triangle, even though you can't see it. Or so I'm told.
As far as I know, everything that you can't see on screen is implicitly outside of Clip Space, and therefore not rendered ... But maybe there's something that I don't know about.
In either case, here's a complete zoom example written in C, using SDL for basic OpenGL context and input handling:
[source lang="cpp"]/*
* zoomdemo.c
*
* Zooming example by Goran Milovanovic, for Lance42.
*
* Arrow keys move the little square around.
* W key zooms in; S key zooms out.
* ESC to quit (or just close the window).
*
* Compile command used: gcc -Wall -o zoomdemo -lGL -lSDL zoomdemo.c
*
*/
#include "SDL/SDL.h"
#include "GL/gl.h"
SDL_Surface* createDisplay(short width, short height){
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_Surface* screen = SDL_SetVideoMode(width, height, 32, SDL_OPENGL);
return screen;
}
void processEvents(char* keyboard){
static SDL_Event event;
while ( SDL_PollEvent(&event) ){
switch (event.type){
case SDL_KEYDOWN:
keyboard[ event.key.keysym.sym ] = 1;
break;
case SDL_KEYUP:
keyboard[ event.key.keysym.sym ] = 0;
break;
case SDL_QUIT:
exit(0);
}
}
}
void glInit(SDL_Surface* screen){
// Set clear color (black)
glClearColor( 0, 0, 0, 1 );
// Set projection matrix
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
float aspect_ratio = (float)screen->w / screen->h;
float X = 10;
float Y = X / aspect_ratio;
glOrtho( -X, X, -Y, Y, 1.0, -1.0 );
// Set modelview matrix
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
void glZoom(float scale){
glMatrixMode(GL_PROJECTION);
glScalef(1 + scale, 1 + scale, 1);
}
typedef struct Vec2{
float x;
float y;
} Vec2;
typedef struct Square{
Vec2 v_coords[4];
Vec2 pos;
} Square;
void squareInit(Square* square){
Vec2* v = square->v_coords;
v[0].x = -1; v[0].y = 1; // 0-----1
v[1].x = 1; v[1].y = 1; // | |
v[2].x = 1; v[2].y = -1; // | |
v[3].x = -1; v[3].y = -1; // 3-----2
square->pos.x = 0;
square->pos.y = 0;
}
void squareDraw(Square* square){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(square->pos.x, square->pos.y, 0);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(2, GL_FLOAT, 0, square->v_coords);
glDrawArrays(GL_QUADS, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
}
int main(int argc, char* argv[]){
SDL_Surface* screen = createDisplay(640, 480);
glInit(screen);
char keyboard[322];
memset(keyboard, 0, sizeof(keyboard));
Square square;
squareInit(&square);
while (1){
processEvents(keyboard);
if (keyboard[SDLK_ESCAPE])
break;
glZoom((keyboard[SDLK_w] - keyboard[SDLK_s]) * 0.1f); // Incremental zoom
// Move the square
square.pos.x += (keyboard[SDLK_RIGHT] - keyboard[SDLK_LEFT]) * 0.25;
square.pos.y += (keyboard[SDLK_UP] - keyboard[SDLK_DOWN]) * 0.25;
glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer, so we can draw to a clean slate.
squareDraw(&square); // Draw whatever you want to draw.
SDL_GL_SwapBuffers(); // Update the screen with the newly rendered image.
SDL_Delay(16); // Close enough to 60 fps.
}
return 0;
}
[/source]
I'm doing it the "right way" as Trienco rightly pointed out: My glOrtho call creates a symmetric projection, and the zooming is done by simply scaling the projection matrix.
If you have any questions, feel free to ask.