8

Original Question

I want to use 'gluPerspective', 'glViewport' and 'gluLookAt' to manipulate my camera and screen.

Which functions to I apply to which matrix mode? And in what order should I / must I use them?

For example, I am trying to set up my screen and camera like this: (But it is not working!)

glMatrixMode(GL_PROJECTION) // Apply following to projection matrix - is this correct?
glLoadIdentity(); // Reset first
glPerspective(45.0, (double)w/(double)h, 1.0, 200.0); // Set perspective
glViewport(0, 0, w, h); // Set viewport

glMatrixMode(GL_MODELVIEW); // Apply following to modelview - should glViewport come under here?
glLoadIdentity(); // Reset first
gluLookAt(px, py, pz, cx, cy, cz, ux, uy, uz); // Set position, centre and then up vectors
// This surely comes after calling GL_MODELVIEW?

I have looked around for online documentation, and I understand the functions, just not where they should go and in what order!

Some time later...

It is several months later now and I am adding a quick edit to show the system I use to render things with OpenGL. This is to help others who see this question in the future.

I primarily use two methods.

Method 1:

This method groups everything together.

// Firstly, the window may have been resized so re-create the viewing area
glViewport(0, 0, width_of_window_rendering_area, height_of_window_rendering area);

This recreates the viewport for rendering over the entire area of the inside of the window. With sfml, you would do something like window.width() or window.height(), or something similar depending on which windowing toolkit you use (glut, glfw, sdl etc)...

// The second step is to add a projection matrix. There are three main ones I like to use
// Uncomment the one you want
glMatrixMode(GL_PROJECTION); // Tell OpenGL to manipulate the correct matrix stack
glLoadIdentity(); // Reset the projection matrix, or bad things happen after multiple calls to below functions!
// glOrtho( ... ) // Uncomment to use 2D rendering
// gluPerspective( ... ) // Uncomment to use (easy) 3D rendering
glFrustrum( ... ) // Uncomment to use (harder/less intuitive?) 3D rendering
glMatrixMode(GL_MODELVIEW); // I always prefer to leave OpenGL in the modelview manipulation mode.
    // I consider it the "default" and safest mode to leave OpenGL in, as any rogue
    // calls to functions changing its contents is likely to mess up your geometry
    // which should be visible as a problem on the screen, which tells you you need
    // to fix something! Manipulating the other matrix stacks may not show obvious
    // problems.

You will need to select one of the three out of 'glOrtho', 'gluPerspective' and 'glFrustrum'. There is also 'gluOrtho2D', but use that with care! (I prefer to specify near and far planes myself with 'glOrtho'.) You need to replace the '...' with your arguments to the function also.

// The third step is to clear the screen and set your camera / geometry position
glClear(GL_COLOR_BUFFER_BIT); // use bitwise OR ('||') with 'GL_DEPTH_BUFFER_BIT' and 'GL_STENCIL_BUFFER_BIT' if required
gluLookAt( ... );
// I like to use gluLookAt, or at least I _italic_used to! Now I implement my own camera...
 // That is another fun thing you should try if you are comfortable with 3D geometry and hard math!

// The fourth step is to draw your scene. You may want to put lighting stuff first or in with the drawing
glutWireTeapot( ... );

Method 2:

The second method is the same as above, but to move the first step into a separate function. Then you must detect window resize events and call this function. With glut, you can specify a callback. With SFML you can detect an event when the window is resized. I forget how SDL works, but it is similar. I have not yet learned how glfw works.

Hopefully that will help you.

Some OpenGL novices (probably myself included at one time) try to specify camera translations on the PROJECTION matrix. Do not do this - I head it messes up lighting and possibly other things.

Community
  • 1
  • 1
FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225
  • What you have there looks appropriate to me. Perhaps your error is elsewhere. – Tim Oct 24 '12 at 16:23
  • Make sure your scene is in between the near and far planes you specified in glPerspective. – max Oct 24 '12 at 16:24
  • If you understood the functions, you would understand where they go. For example, you seem to believe that `glViewport` creates a matrix. It does not. – Nicol Bolas Oct 24 '12 at 16:27
  • "But it is not working!"...segfault? Bluescreen? Kernel panic? Wipes your home directory? Monitor catches on fire? *Printer* catches on fire? Gives rise to [dom](http://cm.bell-labs.com/who/dmr/odd.html)? – genpfault Oct 24 '12 at 16:28
  • Haha, @genpfault - my that I mean blank screen, the printer is fine! ;) – FreelanceConsultant Oct 24 '12 at 16:32
  • What I am asking is am I manipulating the correct matrices? And at I manipulating them in the correct order? – FreelanceConsultant Oct 24 '12 at 16:33
  • If you didn't understand the question, you should not have commented. Max has given me the answer I was asking for. – FreelanceConsultant Oct 24 '12 at 16:38

1 Answers1

3

I define my reshape callback function as:

Call glViewport(...) once in the beginning.

Then reload the projection matrix with an identity matrix:

glMatrixMode(GL_PROJECTION);
glLoadIdentity();

Then:

glPerspective(...)
glMatrixMode(GL_MODELVIEW);

gluLookAt(...) can be called anytime later if you need to change your camera position.

Works for my simple purposes.

max
  • 4,248
  • 2
  • 25
  • 38
  • Thanks, this is the answer I was looking for. If I call gluLookAt twice, will it move the camera again? In the same way, calling glRotatef twice WILL rotate the camera/scene twice, will gluLookAt do the same? – FreelanceConsultant Oct 24 '12 at 16:36
  • Sorry, another question: Does glViewPort edit a matrix? Should I call glMatrixMode(GL_PROJECTION) before any call to glViewPort? – FreelanceConsultant Oct 24 '12 at 16:37
  • Yes, it will rotate the whole scene twice. But if you put it in your display callback function, then remember the display function is called repeatedly, you have to load the model view matrix with an identity matrix in the beginning of your display callback function. – max Oct 24 '12 at 16:39
  • Thank you @Max this is extremely helpful and it works perfectly now. Can't thank you enough - it not only works perfectly I now actually understand what I'm supposed to be doing. – FreelanceConsultant Oct 24 '12 at 16:43
  • No, there is no need to call glMatrixMode(GL_PROJECTION) before glViewport. glViewport is supposed to be called when your window is resized i.e. you need to resize your viewport. So put it in your reshape callback function. – max Oct 24 '12 at 16:43
  • In which case, glViewPort does NOT manipulate a matrix stack? I will have a google... :) – FreelanceConsultant Oct 24 '12 at 16:45
  • See this link: http://www.opengl.org/discussion_boards/showthread.php/134395-matrix-of-glviewport – max Oct 24 '12 at 16:49
  • @Max: glViewport is not meant to be called when the window is resized. glViewport is meant to be called, when the viewport must be set. In a split screen game this happens at least twice when rendering a single frame (left pane and right pane). Also glViewport does not act on any matrix. It can be changed at any time and the effect is immediate. – datenwolf Oct 24 '12 at 18:01
  • @datenwolf Yeah I shouldn't have written that. Thanks! – max Oct 24 '12 at 18:08
  • whats the difference if i call glulookat before/after gluperspective? – suitianshi Feb 17 '14 at 15:02