2. OpenGL Window Reshaping (Version 2.0)
Introduction
In a poorly written OpenGL application, you may notice that when you resize your window, your geometry will not transform to match the size and aspect ratio of your new window size. Your geometry may stay the same size even though the window is smaller or larger and what we want is for our geometry to scale with our window. This is because when GLUT sets up our window, it will initially set some default values for us, but GLUT doesn’t keep track of this information as the window changes, and for good reasons, every application has different needs, and there are no default magic values for everyone.
To fix this, we need to tell GLUT how we want our scene to be rendered, and to do so, we need to understand a little more about OpenGL matrices, and matrices in 3D applications in general. Now there are three main matrices in OpenGL, those being the Projection Matrix, Model View Matrix and the Texture Matrix.
Projection Matrix
The Projection Matrix, just like most matrices in 3D is a 4×4 matrix. This matrix provides the information needed to map a 3D scene to a 2D plane. In the case of OpenGL, this 2D plane is known as our Colour Buffer and this stores the image that we see rendered to our GLUT window, although rendering of the Colour Buffer to a window is not required for off-screen rending. In order to set up our Projection Matrix, we need to tell OpenGL the angle in degrees of our field of view, the aspect ratio for our window which will be our 2D rendering plane, and the near and far planes that bound our render.
Model View Matrix
The next main matrix is the Model View Matrix, which is also known as your Transformation Matrix. This matrix tells us the location and rotation of our geometry placement at any point in time. If you want to move an object, you will be modifying your Model View Matrix, without even knowing it.
Texture Matrix
The Texture Matrix is something you usually don’t want to touch. This is similar to the Model View Matrix as it is also a Transformation Matrix, but it is used for manipulation the position and rotation of textures in texture space. Personally I have only ever used this as a spare matrix when passing information through to GLSL shaders, but in fixed function rendering (standard OpenGL), you won’t want to touch this unless you have a specific reason.
Coding
So let’s now take a look at setting up how to reshape our window.
If you are following through my tutorials, each one will build upon another, and this one builds on top of the first tutorial on creating a window with GLUT. So for this tutorial you will want to open up the code from the previous tutorial.
Now go ahead, and create a new method called “reshape” which takes in two integer values and returns a void. The two incoming parameters will be sent via GLUT, and will contain the width and the height of the window at the point in time that it is called.
It should look something like this:
void reshape (int width, int height) { }
Then down inside the main method, we need to let GLUT know which method to use for our reshaping, this is done almost identically to how we told GLUT to use our display() method. After the line:
glutDisplayFunc(display); // Tell GLUT to use the method "display" for rendering
Add the line:
glutReshapeFunc(reshape); // Tell GLUT to use the method "reshape" for rendering
Now that GLUT knows which method to call, let’s fill it in so that it actually does something.
The first thing we are going to do is tell OpenGL the size of our viewport (the 2D plane) that we want to render to. We are going to tell OpenGL to start at (0, 0), which corresponds to the bottom left of our window, and then we will tell it to take the size (width, height), which will give us the top right of our window.
glViewport(0, 0, (GLsizei)width, (GLsizei)height); // Set our viewport to the size of our window
Once we have setup the size of our viewport, we need to switch to our Projection Matrix so that we can setup how our scene is rendered.
glMatrixMode(GL_PROJECTION); // Switch to the projection matrix so that we can manipulate how our scene is viewed
Now that we are in the correct mode, we are going to reset our Projection Matrix to the identity matrix so that we don’t cause any artefacts.
Forgetting to reset matrices is a big cause of unusual rendering as OpenGL adds on the previous matrix every time something is called. In the case of setting the Projection Matrix, it would be like trying to apply the projection on to the current projection.
glLoadIdentity(); // Reset the projection matrix to the identity matrix so that we don't get any artifacts (cleaning up)
Now we are ready for the core of this method. The following line will setup the parameters for our view, such as the field of view, aspect ratio and the near and far planes. The first variable that I am going to set is the field of view (FOV), which I am going to set to 60 degrees. This gives us a viewing angle of 30 degrees to the left, and 30 degrees to the right.
The next value after that is the aspect ratio of our window, which is calculated by dividing the width of our window by the height. The last two values are the near and far plane, and I am going to set them to 1.0 and 100.0 respectively. This means that anything with a position less than 1.0 unit (away from the camera) won’t be drawn and anything with a position greater than 100.0 units (away from the camera) won’t be drawn.
gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes
The very last thing we need to do in our method is switch back to the Model View Matrix. If we forget to do this, then we will be trying to position our geometry according to our Projection Matrix, and we do not want this.
glMatrixMode(GL_MODELVIEW); // Switch back to the model view matrix, so that we can start drawing shapes correctly
And that should do it, just make sure everything compiles, and when we add some geometry, you can see this method in action.
It doesn’t seem like much, but this is an extremely important method. You will want absolute control over your field of view, and near and far planes in most applications you write.
If you have any questions, please email me at swiftless@gmail.com
#include <GL/glew.h> // Include the GLEW header file #include <GL/glut.h> // Include the GLUT header file void display (void) { glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red glClear(GL_COLOR_BUFFER_BIT); //Clear the colour buffer (more buffers later on) glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations glFlush(); // Flush the OpenGL buffers to the window } void reshape (int width, int height) { glViewport(0, 0, (GLsizei)width, (GLsizei)height); // Set our viewport to the size of our window glMatrixMode(GL_PROJECTION); // Switch to the projection matrix so that we can manipulate how our scene is viewed glLoadIdentity(); // Reset the projection matrix to the identity matrix so that we don't get any artifacts (cleaning up) gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes glMatrixMode(GL_MODELVIEW); // Switch back to the model view matrix, so that we can start drawing shapes correctly } int main (int argc, char **argv) { glutInit(&argc, argv); // Initialize GLUT glutInitDisplayMode (GLUT_SINGLE); // Set up a basic display buffer (only single buffered for now) glutInitWindowSize (500, 500); // Set the width and height of the window glutInitWindowPosition (100, 100); // Set the position of the window glutCreateWindow ("Your first OpenGL Window"); // Set the title for the window glutDisplayFunc(display); // Tell GLUT to use the method "display" for rendering glutReshapeFunc(reshape); // Tell GLUT to use the method "reshape" for rendering glutMainLoop(); // Enter GLUT's main loop }
Hi,
I would just like to clarify if I understood this line of code correctly
gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0);
it states here that the 3rd and 4th parameter states that the object can only be seen when it is within 1-100 on the z-axis? 1 is the farthest from the screen and 100 is the nearest because on the z axis positive value is going towards you and negative value is going away from you? Because when I apply this tutorial I have to add translation matrix glTranslatef(0, 0, -1) before the object is drawn just to be seen. I do not understand why I have to ad that, and -1 on the z-axis is beyond the parameter of 1-100 that was set? If I am not mistaking the default value of the translation matrix is (0, 0, 0);
Hope you anyone can shed some light for me on this one. 🙂
Hi Marlo,
In short, gluPerspective takes positive values but we end up with negative values. eg: -1 and -100 going into the screen. I’d recommend reading up on OpenGLs coordinate system and projection matrices if you’re really interested.
Thanks,
Swiftless
Hi Swiftless,
Thank you replying to my comment, I really appreciate it. I will this suggestions you gave me, thanks a lot. After reading this chapter, then I proceeded to the next chapter, and you mention there about how the camera is place on the OpenGL world and also why we needed to use glTranslate.
I’m trying to complie with gcc. First part of turorial was ok using this command:
gcc main.c -o main -L/user/include/X11 -IGL -IGLU -lglut (on Debian 7)
but this seccond part I receive this error message:
main.c:(.text+0x6d): undefined reference to `gluPerspective’
collect2: error: ld returned 1 exit status
I thought it was the ‘#include ‘ missing, but nothing happens.
If I have 2 different glMatrixMode’s in the reshape function, it wont render anything.
Example:
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60, (GLfloat)width/(GLfloat)height, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
Will render nothing.
If I change GL_PROJECTION to GL_MODELVIEW or vice versa it renders the square just fine although it will not resize when i’m still holding the window.
Why is it important to switch between the projection and model view matrices?
What are their functions?
Could you explain the roles of these matrices?
i see a few people have this question here. i had the same question but ive put some thought into it.
this is how i see it (i might be wrong, but it seems logical)
all it is is that you call GL_PROJECTION to manipulate the scene and set values as needed.
then once your done setting the values you call GL_MODELVEIW to go back into veiwing mode
which you then render from that veiw.
if anyone knows different then correct me if im wrong but as a begginer opengl enthusiast
this is how i interpreted it.
@swiftless::Gr8 tutorial for beginners…can you tell me about fire effects and water ripples…I really need to know.
I want to know difference between your openGl tutorial and Nehe OpenGl tutorial.Nehe tutorial seems more difficult .Which method is best yours or Nehe.
There is no best method. NeHe covers a lot of things that I don’t or haven’t gotten around to yet. However when I first started, I also had a little trouble digging into NeHe’s tutorial so I decided to write my own which are more bare-boned.
Dude,
I have been coding opengl on and off since 2000 and yours is one of the best tutorials Ive ever seen so far.
Keep up good job!
Erol
i’m using openGL in Linux [cent OS]
static GLfloat Matrix::det4x4(float a1, float a2, float a3, float a4,
float b1, float b2, float b3, float b4,
float c1, float c2, float c3, float c4,
float d1, float d2, float d3, float d4); //line 105
static GLfloat Matrix::det3x3(float a1,float a2,float a3,
float b1,float b2,float b3,
float c1,float c2,float c3); //line 109
static GLfloat Matrix::det2x2(float a, float b,
float c, float d); //line 112
ON RUNNING the code i’m getting the error below
help me debug…
[gowravi@localhost pp3]$ gcc -lglut main.cpp
matrix.h:105: error: extra qualification ‘Matrix::’ on member ‘det4x4’
matrix.h:109: error: extra qualification ‘Matrix::’ on member ‘det3x3’
matrix.h:112: error: extra qualification ‘Matrix::’ on member ‘det2x2’
[gowravi@localhost pp3]$
hi i m doing simple programs in graphics, i m getting previous output displayed in the window after making changes in the program… can u help me..
Again, very impressed with this 2nd part.
Clearly you are an expert at teaching.
I have little experience with matrices and vectors, and I’m just starting with
vector calculus.
But you put things so simple and understandable.
Thank you.
This means that anything with a position less than 1.0 unit (CLOSE to the camera) won’t be drawn
Im using visual studio 2010 ultimate, and while compiling im getting these errors.
1>—— Build started: Project: cohen_suth, Configuration: Debug Win32 ——
1>LINK : error LNK2001: unresolved external symbol _mainCRTStartup
1>F:\Projects\cohen_suth\Debug\cohen_suth.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
can someone help me
Hi, which OS you are using? Have to follow diff setup methods for both 32bit and 64bit machine… I can tell you the steps to be followed, if you tell me the machine….
Nice tutorial man,
Need to know one thing, if say I dont want my app to handle resizing, so if I simply write a code to draw points or lines, will it work. Please see my post here
http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=300938
-anoop
Hello Swiftless,
First of, thanks for these great tutorials, I’ll donate some money to you shortly for doing such a great job on these. Keep it up!
Now, onto my question: Will resize be called on creation of the window? Or only when resizing?
Thanks,
Ruud
Hi,
Is this normal that i don’t understand almost nothing from the beginning?
Hi Evaldas,
If you have absolutely no computer graphics experience and very little matrix and verctor experience, then yes that would be normal. I’d recommend looking at maybe the Wikipedia pages for vectors, matrices, transformation matrices and projection matrices if you really want to understand what is going on.
Thanks,
Swiftless
Good tutorials , but screenshot of the image for each program will be a wonderful addition
i have created a game through OpenGL. But the contents of the window vanishes when the window is moved or so… what can i do?
I love yours tutorials!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Great work. Very helpful.
You should have written a code to generate a ‘square’ in display(). And then demonstrate the use and need for maintaining the aspect ratio using reshape(). i.e.,
“when the window is resized the Square remains in shape of a ‘square’ and doesn’t become a rectangle due to resizing”.
Hi Tejus,
I had an internal debate over the ordering of this, and came to the conclusion I wanted to get all the fiddly bits down before people started playing around with shapes and getting distracted.
Thanks,
Swiftless
Your tutorials have been very helpful.
thank you.
hi swiftless
i don’t feel there is something changed than the programme in first tutorial.
Hi Zilot,
The reshape function makes a subtle, but important change to the application. But you won’t notice the difference until you start rendering shapes and then resizing your window. Not only does it set the size of the OpenGL context to the size of the window it is in, but it makes sure everything is perspectively correct.
Cheers,
Swiftless
Hello
I am following this tut up and building pong on this however i need to know the boundries of the window as i give it a 500 by 500 window and then its comes out with somthing like 0 – 5.89 as the boundries. so how can i get that sort of information.
Andy A
Hi Andy A,
For a game such as pong, if you don’t want 3D, you can simply use orthographic mode which lets you place things on a per pixel level. Otherwise you will need to do a conversion from 3D to 2D. This means multiplying the 3D vertex by the perspective matrix to get the coordinates in screen space. Otherwise you can setup a controlled environment, calculate the edges in 3D space prior and set these values as the border of the scene.
Cheers,
Swiftless
when I follow all tutorial 2 I try compile and visual studio 2010 show this message
—— Build started: Project: synthcam, Configuration: Debug Win32 ——
main.cpp
c:\program files\microsoft visual studio 10.0\vc\include\stdlib.h(353): error C2381: ‘exit’ : redefinition; __declspec(noreturn) differs
c:\program files\microsoft visual studio 10.0\vc\include\glut.h(146) : see declaration of ‘exit’
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Hey Gil,
It sounds like you have included your headers in the wrong order.
Cheers,
Swiftless
Hi,
I was trying out your example. but I was not able to understand the purpose of this one. The window remains red even when I resize the window.
Perhaps I am missing something . or does this project demonstrate any geometry being scaled?
Thanks,
Nice tutorials !!
Hey Sahilesh,
This tutorial doesn’t draw any geometry so you will not see the effect, but it is a lead up to when we render geometry, everything will be in place.
Cheers,
Swiftless
The page didn’t print the stuff in the angle brackets…html problem I suppose: (just change the following brackets to angle brackets)
change:
#include (GL/glew.h)
#include (GL/glut.h)
to:
#include (GL/freeglut.h)
Much better…
Thanks for posting.
Hopes this helps…
I’m following along on my Linux box and had to make a couple changes to make it compile. Assuming that you are using freeglut here goes:
change:
#include
#include
to:
#include
and to compile add the following:
-lglut -lGLU
Hi,
Could you tell me how we can integrate EGL with opengl.
I am not a big fan of glut.
Thanks
Ranjith
Hi Ranjith,
Unfortunately I don’t have any experience with EGL.
Cheers,
Swiftless
“we are going to reset our Projection Matrix to the identity matrix ” .. what is an identity matrix? did you explain that in last tutorial?
Hi Imrn,
These tutorials are meant to be more on OpenGL and Computer Graphics, not so much on the maths. If you want to know in detail about the different matrices then I suggest you look around.
The identity matrix is just an empty matrix with 1’s along the diagonal.
Cheers,
Swiftless
Hi,
I’m following your tutorial with Ubuntu Linux. All the programs are working perfectly, but compiling them has been a little tricky.
Of course, I know I have to include “GL/glut.h” and link “-l glut”. It worked perfectly in chapter 1.
Now, gluPerspective() is not declared in “glut.h”, it is declared in “glu.h” and my compiler complains about it. I also have to link “-l GLU” to compile the program described here.
I don’t know how things work in Windows, but I believe “GL/glu.h” should be included in the programs.
Hope it helps.
Hey Juan,
I target these tutorials a lot more towards Windows developers because thats where a majority of people come from. However I personally am a fan of OSX development, which also requires manual linking when using gcc, but I tend to stick to using Frameworks these days which are OSX only. I used to include “GL/glu.h” in my applications, but find that I don’t need to anymore as it’s included in other header files that I use (on Windows anyway). It’s good to hear you got it working though.
Cheers,
Swiftless
hi
I have a doubt in this document.
In this reshape function you used two matrix(projection and modal )
what is the necessity to use like this?
Great tutorial!
One ponint to mention: fov is in y direction
Hi, I just wanted to say that this is probably the best opengl tutorial on the web, thanks!
Tutorials are very helpful.
i tried all practically.. working fine.
Hi Expora,
Most of the methods we create for use with GLUT are void methods, yes. Meaning they don’t return a value.
Also, the method “reshape” can be called whatever you like, as long as it takes the same types of parameters.
I’m not sure what you mean about the int’s. Do you just want to know what they are? An int is short for integer, and an integer is just a whole numer (no decimal points).
Cheers,
Swiftless
Hello there!! Quick question: Methods always use void at the beginning? also do you assing the reshape name on your own or does it means something in GLUT? Also I would like to know what exactly int. I mean I’d like to know what I’m writing so I can go do things of my own someday 😀
Thanks,
Expora
hi..i m still gettin errors even if i follow ur methods..is there any alernative..??please tell me the possible errors
Hi Anjana,
You shouldn’t be getting any errors if you completed the first tutorial successfully. What errors do you get?
Cheers,
Swiftless