OpenGL glMatrixMode help - c++

I'm starting to work a little on OpenGL stuff, and I'm seeing a lot of examples that make calls to the glMatrixMode function.
From what I've gathered, setting this to either GL_MODELVIEW or GL_PROJECTION (etc) will activate that specific transformation matrix and all subsequent calls to matrix transformation functions (glTranslatef, glPushMatrix, glLoadIdentity, glLoadMatrix etc) will affect the active matrix only.
What I don't get is why are there 3 (4 in some cases) different matrices? Which one should I use? (I'm probably going to get a lot of "Use Shaders", but I can't. Limited by school...) When should I switch and activate a different matrix? What is the benefit of utilizing all of them as opposed to only using one?
Thanks for any help :)

glMatrixMode doesn't "activate" matrices. The OpenGL fixed pipeline uses 3 matrices (sometimes 4): Two are responsible for transforming the geometry, one for transforming texture space (and some implementations one for color adjustments). Those matrices are used all the time.
The modelview matrix is used to move geoemtry around. Since OpenGL doesn't have a "camera" the viewer is positioned by moving all the geometry in the opposite (=inverse) of the movements of the "camera".
The projection matrix is used to transform the geometry from modelview space into clip space, i.e. it projects the transformed geometry into the viewport.
The texture matrix transforms the texture coordinates. In case (s,t,r,q) are directly given the benefit of this matrix isn't clear at first. But OpenGL also allows to generate texture coordinates from the vertex positions. This together with the texture matrix allows to implement projection textures.
The color matrix is seldomly used and not even available in all implementations (it's part of an extension). If available it transforms the incoming vertex colours. Since there are not implicit color generators what use is then? Well, it can be used to transform between linear colourspaces, e.g. RGB->XYZ or any other colour space conversion that can be expressed as a matrix of scalars. Nobody used the color matrix these days, shaders do the job much better.
glMatrixMode is there so that there's no bloat of functions. Otherwise you'd need:
glModelviewLoadIdentity
glModelviewLoadMatrix
glModelviewMultMatrix
glModelviewRotate
glModelviewTranslate
glModelviewScale
glModelviewPushMatrix
glModelviewPopMatrix
glProjectionLoadIdentity
glProjectionLoadMatrix
glProjectonMultMatrix
glProjectionRotate
glProjectionTranslate
glProjectionScale
glProjectionPushMatrix
glProjectionPopMatrix
and so on. Also you couldn't use functions like glFrutum in both projection and texture matrices. You'd need two of those, too.
And last but not least one important hint. Setting the viewport and the projection matrix belongs in the rendering function. Most tutorials you'll see out there place them in the window resizing handler, which is the totally wrong place for that. Don't immitate this bad habit.

You will be using all of these if you use the fixed function pipeline (i.e. "no shaders"). In fact, you'll use them with shaders too, but you'll implement them yourself in that case.
This part of OpenGL can be hard to grasp at first, although it is actually quite simple. When you select a particular matrix, then this does not turn on or off anything. All it does is that it makes functions like glTranslatef work with the one specific matrix that you've selected.
OpenGL works like this everywhere (except for direct state access), for example with textures and buffers, in the same way.
EDIT: As for why there are several matrices, they all do different things. Your models are usually in their "own space", which means they need to be somehow transferred to the "world", by scaling them appropriately and translating them to the right location. Then everything (the whole "world") needs to be transformed in a way according to your "eye position", and it must be transformed into a "normalized" clip space, because that is how the hardware can be implemented in the most efficient manner, etc, etc, etc.
All those matrices are usually multiplied together (without you knowing that this happens).If you google for opengl transform pipeline, you will get a lot of good resources that explain what happens when in detail, for example this.
Or, read the specification (freely available at opengl.org), it contains very explicit (and in my opinion easy) information on how all the seemingly complicated matrix stuff is intended.

You will probably just use glMatrixMode(GL_PROJECTION) once, followed by gluPerspective() (or maybe glOrtho()), so that you will set how the projection will be done. It is not that very common to change the perspective once set.
Then you change to GL_MODELVIEW and just use it to rotate/translate/scale stuff around. Both matrix are used on redering, being final position on screen = GL_PROJECTION * GL_MODELVIEW * your vertex. But since GL_MODELVIEW should change much more often than GL_PROJECTION, they are separated by the specification.

It's because matrix multiplies are not commutative. If you only had one matrix mode, the new transformation would always occur after all existing ones, and that's not always desirable.
By keeping several matrices which effectively get multiplied together for each piece of geometry, it's possible to e.g. have both translation to render the different bits of an object and also a point-of-view transformation, and be able to adjust these independently of each other.

Related

Does OpenGL change vertices in memory when you apply transformations?

So let's say I have a single vertex (to make things easy) in my program, (0, 0, 0). Right at the origin. I render a single frame with a simple translation matrix, moving the vertex two units down the x-axis. The vertex is rendered accordingly. Does the same vertex now show up in the VRAM as
(2, 0, 0)? I've read that it's important to load all the respective identity matrices in OpenGL every time a frame is rendered--and I assume that's because everything would continually move, rotate, etc. further and further, implying that applying transformations DOES modify actual data, not just the appearance onscreen.
Strictly speaking, OpenGL is just an API definition. An implementation can do whatever it wants as long as it meets the specifications.
That being said, the answer to your question is generally: NO. It's hard to picture how storing transformed vertices back into the memory that also contained the original vertices would ever make sense.
The original vertex positions are passed into the vertex shader, where they are processed, which can include transformations. Once they exit the vertex shader, the transformed positions will most likely be stored in some kind of cache or dedicated on-chip GPU memory until they are processed by the next steps of the pipeline, which includes perspective division, application of the viewport transform, and rasterization. Once those vertex processing steps are completed, the transformed vertices can be discarded. They may stay in a cache for a little longer, for possible reuse of the processed vertex in case the same original vertex is used again. But they are not stored in any persistent way.
The way I interpret it, what you heard about having to reset the matrices for each frame was probably a misunderstanding. If you want to apply the same matrices in the next frame, you don't have to do anything at all.
What they were most likely talking about is related to how the matrix stack in legacy OpenGL works. Most calls that modify the current matrix, like glTranslatef(), glRotatef(), etc, are applied incrementally to the current matrix. For example, if you call glRotatef(), the rotation is combined with the transformation that was already on the matrix stack. The result it that your newly specified rotation is applied to the vertices first, followed by the transformations that were already on the matrix stack.
Based on this, if you want to specify transformations from scratch at the start of each frame, you will call glLoadIdentity() to reset the current transformation on the matrix stack before you start specifying your new transformations. Or you can use glPushMatrix()/glPopMatrix() to save and restore the desired state of the matrix stack.
If you use what many people call "modern OpenGL", meaning that you don't use the legacy fixed pipeline functionality, you don't have to worry about any of that. The matrix stack is gone for good, and you get to calculate your own transformation matrices, and pass them to your shader code.
Here is a link on wiki about the mathematics involved with Transformation Matrices. https://en.wikipedia.org/wiki/Transformation_matrix this will give you an understanding of the math behind the scenes. Another way to look at this is also on the lines of linear or vector algebra. So what happens under the hood when you render a scene is that all of the vertex (pixel) data is sent from the CPU to the GPU to be rasterized and drawn to the screen. This is your batch process or render call, now you also have a frame function that will happen x amount of times per second which will give you your frames per second. So if you are rendering at say 60 FPS then these pixels, vertices, triangles etc., will be drawn 60 times each second. When you apply a transformation to this set of vertices what happens here is you have a transformation matrix that is being multiplied to your model view projection matrix. MVP * T which this will be saved back into your existing MVP matrix if this is how you have your calculations set up. There are some differences between which version of OpenGL you are using as you go from OpenGL v1.0 Pure CPU calls up to v4.5. As far as I know after version 3.2 or 3.3 I don't remember which version off hand you have to implement the MVP yourself where versions greater than v1.5 where shaders were first introduced was handled for you already. Here is the documentation on OpenGL https://www.opengl.org/ and on the main page there will be a topic that says documentation from there you can either select OpenGL Registry or which ever specific version you want to look at. From here you can read their documentation about the OpenGL API since this site covers everything that is available in their API. So as you begin to understand this process, yes the actual coordinate data for these vertices does change, however it will not continuously change unless you are incrementing a static type variable with a factor of time thus giving you some kind of simulation of movement or animation. If you apply only a single transformation then these pixels, vertices, triangles, etc., will either Rotate, Translate, Scale, or Shear depending on which Transformation you are applying. I will tell you that the order of these operations does matter, but I will not tell you which order they are, that will be for you to read up on and to figure out. These reason this does matter is due to the fact that not every Matrix Multiplication has a valid Inverse Matrix. The Identity is used for reasons such as round off errors and floating point precision, so that if you happen to apply say 1,000 transformations in a matter of about 10 seconds, you do not have astronomical errors. This should be enough to point you in the right direction and also serve as a guide as to how the OpenGL API works.

How to scale a matrix obtained with glm::lookat()?

I am trying to create an orthographic view (separate from the final perspective view). I know the view's scale, position, it's up vector, and the point it's looking at. So it seems easiest to simply use glm::lookAt() to create the view matrix, except there's no way to specify scale.
Is there a way to introduce scaling with glm::lookAt()? I don't think it's possible to scale the matrix made by lookAt, since scaling needs to happen first to get the 'expected' result (objects appearing larger or smaller, like zooming a camera in or out). I may be wrong there though.
If it's not possible while using lookAt, is there a series of glm functions that would be equivalent?
In terms of matrix transformations, you can start with a scale and apply the glm::lookAt() matrix afterwards. I'm not familiar with glm, but I have used GLUT before. You should be able to do a matrix multiplication like this (I'm assuming that you've already transformed everything into scene space, defined all the variables etc.)
TransformedVector = glm::lookAt(cameraPosition,
cameraTarget,
upVector) *
glm::scale(scalingFactor,
scalingFactor,
scalingFactor) *
OriginalVector;
If this behaves peculiarly try swapping the glm::lookAt() and glm::scale() order.

How do I access a transformed openegl modelview matrix [tried glGetFloatv()]?

I am trying to rotate over the 'x' axis and save the transformed matrix so that I can use it to rotate further later; or over another axis from the already rotated perspective.
//rotate
glRotatef(yROT,model[0],model[4],model[8]);//front over right axis
//save model
glGetFloatv(GL_MODELVIEW_MATRIX, model);
Unfortunately I noticed that openGL must buffer the transformations because the identity matrix is loaded to model. Is there a work-around?
Why, oh God, would you do this?
I have been toying around with attempting to understand quaternions, euler, or axis rotation. The concepts are not difficult but I have been having trouble with the math even after looking at examples *edit[and most of the open classes I have found either are not well documented for simpleton users or have restrictions on movement].
I decided to find a way to cheat.
edit*
By 'further later' I mean in the next loop of code. In other words, yRot is the number of degrees I want my view to rotate from the saved perspective.
My suggestion: Don't bother with glRotate at all, they were never very pleasant to work with in the first place and no serious program did use them ever.
If you want to use the fixed function pipeline (= no shaders), use glLoadMatrix to load whatever transformation you currently need. With shaders you have to do the conceptually same with glUniform anyway.
Use a existing matrix math library, like GLM, Eigen or linmath.h to construct the transformation matrices. The nice benefit is, that you can make copies of a matrix at any point, so instead of fiddling with glLoadIdentity, glPushMatrix and glPopMatrix you just make copies where you need them and work from them.
BTW: There is no such thing as "models" in OpenGL. That's not how OpenGL works. OpenGL draws points, lines or triangles, one at a time, where each such called primitive is transformed individually to a position on the (screen) framebuffer and turned into pixels. Once a primitive has been processed OpenGL already forgot about it.

Why is there a glMatrixMode in OpenGL?

I just don't understand what OpenGL's glMatrixMode is for.
As far as I can see, when glMatrixMode(GL_MODELVIEW) is called, it
is followed by glVertex, glTranslate, glRotate and the like,
that is, OpenGL commands that place some objects somewhere in
the space. On the other hand, if glOrtho or glFrustum or gluProjection
is called (ie how the placed objects are rendered), it has a preceeding call of glMatrixMode(GL_PROJECTION).
I guess what I have written so far is an assumption on which someone will prove
me wrong, but is not the point of using different Matrix Modes exactly
because there are different kinds of gl-functions: those concerned with
placing objects and those with how the objects are rendered?
This is simple and can be answered very briefly:
Rendering vertices (as in glVertex ) depends on the current state of matrices called "model-view matrix" and "projection matrix";
The commands glTranslatef, glPushMatrix, glLoadIdentity, glLoadMatrix, glOrtho, gluPerspective and the whole family affect the current matrix (which is either of the above);
The command glMatrixMode selects the matrix (model-view or projection) which is affected by the forementioned commands.
(There's also the texture matrix used for texture coordinates, but it's seldomly used.)
So the common use case is:
Have the model-view matrix active most of the time;
Whenever you have to initialize the projection matrix (usually at the beginning or when the window is resized, perhaps), switch the active to projection, set up a perspective, and revert back to model-view.
You can use glRotate and glTranslate for projection matrices as well.
Also: OpenGL supports transforms of textures and colors. If you active this feature you can for example modify the texture coordinates of an object without rewriting the texture coordinates each frame (slow).
This is a very useful feature if you want to scroll a texture across an object. All you have to do for this is to draw the textured object, set the matrix mode to GL_TEXTURE and call glTranslate to set the offset into the texture.
As Nils pointed out, you do have more to matrices than just what you mentioned.
I'll add a couple thoughts:
OpenGL core (from 3.1 onwards) does away with all the matrix stuff completely, so does GL ES 2.0. This is simply due to the fact that shader programs removed much of the requirement of having them exposed at the GL level (it's still a convenience, though). You then only have uniforms, and you have to compute their value completely on the client side.
There are more matrix manipulation entrypoints than the ones you mention. Some of them apply equally well to projection/modelview (glLoadIdentity/glLoadMatrix/glMultMatrix, Push/Pop), They are very useful if you want to perform the matrix computation yourself (say because you need them somewhere else in your application).
All geometry coordinates undergo several linear transformations in sequence. While any linear transformation can be expressed by a single matrix, often you want to think of a sequence of transformations and edit the sequence, and if you have only a single matrix you could only change the ends of that sequence. By providing several transformation steps, OpenGL gives you several places in the middle where you can change the transformation as well.
Calling glMatrixMode before emitting geometry has no effect at all. You call glMatrixMode before editing the transform matrix, to determine where in the overall sequence those edits appear.
(NB: Looking at the sequence makes a lot more sense if you remember that translation and rotation are not commutative, because translation changes the center of rotation. Similarly translation and scaling are not commutative.)

What's the difference between these matrix modes?

GL_PROJECTION and GL_MODELVIEW.
I know there are others, but I, conceptually, can't figure out what the difference between any of them are. When you load the identity matrix after setting the mode, how is the identity matrix any different based on the mode?
One could say that the GL_PROJECTION is for setting up the camera as what it's like, wide lens etc and one could say that GL_MODELVIEW is for setting up the object that is to be drawn, like size and place in space etc.
To position the camera look at the gluLookAt function...
The matrix modes do not change the matrix itself, so identity matrix is identity matrix everywhere.
The matrix modes change which matrix the following commands operate on. That is, whether any subsequent commands work with the projection matrix, or with model*view matrix, or with texture matrices etc.
This might sound a bit confusing, but it's one of OpenGL's design decisions - there's a bunch of commands that operate on some state or object, and only other state settings determine which object exactly they operate on.