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.
Related
I have a little "2 1/2-D" Engine I'm working on that targets multiple platforms, but currently I am upgrading my DirectX 11 version.
One of the things that is really important for my engine to do is to be able to adjust the horizon point so that the perspective below the horizon moves into the distance at a different angle than the perspective above the horizon.
In a normal 3D environment this would be typically accomplished by tilting the camera up above the horizon, however, in my engine, which makes heavy use of 2D sprites, tilting the camera in the traditional sense would also tilt the sprites... something I don't want to do (It ruins the 16-bit-arcade-style of the effect)
I had this working at one point by manually doing the perspective divide in the CPU using a center-point that was off-center, but I'd like to do this with a special projection matrix if possible. Right now I'm using a stock matrix that uses FOV, Near-Plane, and Far-Plane arguments.
Any ideas? Is this even possible with a matrix? Isn't the perpective divide automatic in the DX11 pipeline? How do I control when or how the perspective divide is performed? Am I correct in assuming that the perspective divide cannot be accomplished with a matrix alone? It requires each vertex to be manually divided by Z, correct?
What you are looking for is an off center perspective projection matrix, instead of a fov and aspect ratio, you provide left/right/top/bottom has tan(angle). The result is more or less the same as with a symmetric projection matrix with the addition of two extra non zero values.
You are right also, the GPU is hard wired to perform the w divide, and it is not a good idea to do it in the vertex shader, it will mess with perspective correction for the texture coordinates and clipping ( either not a big deal with the sprite special case ).
You can find an example of such a matrix here : https://msdn.microsoft.com/en-us/library/windows/desktop/bb205353(v=vs.85).aspx
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.
I'm new to OpenGL and was wondering what do we use matrices for, if someone could explain me in abstract intuitive way, because when reading references or any tutorial, all of these take matrices as known mechanism. I've learned matrices in maths, but as English is not my native language, it's hard to figure out what does some stuff mean.
I found good example at www.learnopengl.com which says:
The model matrix. This matrix is used to place a model somewhere in the “world”. For example, if you have a model of a car and you want it located 1000 meters to the east, you will use the model matrix to do this.
The view matrix. This matrix represents the camera. If we want to view our car which is 1000 meters to the east, we’ll have to move ourselves 1000 meters to the east as well (another way of thinking about it is that we remain stationary, and the rest of the world moves 1000 meters to the west). We use the view matrix to do this.
The projection matrix. Since our screens are flat, we need to do a final transformation to “project” our view onto our screen and get that nice 3D perspective. This is what the projection matrix is used for.
This explains it pretty good. But, how do we build them? How large are they?
Also, I've read in this question:
What does glLoadIdentity() do in OpenGL?
that:
glMatrixMode(GL_PROJECTION) deals with the matrices used by
perspective transformation or orthogonal transformation.
glMatrixMode(GL_MODELVIEW) deals with matrices used by model-view
transformation. That is, to transform your object (aka model) to the
view coordinate space (or camera space).
What those transformation mean and how do they get calculated?
I know that here are many question, but I'm trying to make better conception of all of these to get better view on OpenGL. That's why I need some abstract explanation to dive into all details with understanding of conception beyond.
Translation, rotation, and scaling are all affine transforms, which can be implemented using matrix multiplication and addition. Actually, by augmenting the vector with a w element that's always one, the affine transform in 3 dimensions becomes a linear transformation in 4 dimensions and all you need is a matrix multiply.
Doing it with a matrix multiply is very nice because (1) it's fast and (2) you don't need special logic for any of the operations -- you can even compose as many of these affine operations as you want and still represent it with a single matrix.
Having multiple matrix modes is useful when composing. If you had only one matrix, you could add new operations at either end but not in the middle. By having 3 matrices multiplied together later, you can insert new operations at four different points in the order.
The matrix stack is also very useful because it allows you to do an operation for a few primitives and then remove it. If you tried to undo the operation by doing the inverse operation, eventually rounding errors would get out of control. But by remembering the previous matrix, you can just get it back as if the rotation or whatever never happened.
OpenGL is nice in that rather than working with matrices directly, you can call functions that will manipulate them.
So under the hood (what really happens), is that there are several matrices that transform your objects (a model-view matrix that transforms object to camera space, and projection matrix for perspective / orthogonal transformations).
glMatrixMode is like a switch that allows you to choose which type of matrix to use and manipulate, and you specify using the arguments. So glMatrixMode(GL_PROJECTION) means that you will be manipulating the projection matrix.
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.
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.)