1
\$\begingroup\$

I have modest experience of developing games with sdl , libgdx , unity etc. But never got into learning any low level API. So I thought about learning OpenGL and got started with tutorials provided by lazyfoo.net.(Yes I know he is using the legacy OpenGL but he migrates to modern OpenGL as he progresses through the tutorials).

On the fourth chapter he shows the use of glPushMatrix() and glPopMatrix (). Up until then I had the understanding that whenever I translate the modelview matrix that translates the whole gameworld. Now this process of saving the current matrix on stack has put me into some confusions.

They are:
1.If I push the current matrix on the matrix stack and make change to current state, then pop that saved state again; how are these transformations combined into one matrix?

2.In the tutorial he shows how to do scrolling background with four quads in the background.He translates the matrix to position the camera in the proper place based on user input. Then he pops the matrix from the stack in the render method and translates it to four different positions to draw four quads. My question is why don't we see the quads moving with the camera(which means not moving at all relative to the camera) since they are drawn relative to the camera.

In key input function:

//Take saved matrix off the stack and reset it
glMatrixMode( GL_MODELVIEW );
glPopMatrix();
glLoadIdentity();

//Move camera to position
glTranslatef( -gCameraX, -gCameraY, 0.f );

//Save default matrix again with camera translation
glPushMatrix();

in render function:

//Pop default matrix onto current matrix
glMatrixMode( GL_MODELVIEW );
glPopMatrix();

//Save default matrix again
glPushMatrix();

//Move to center of the screen
glTranslatef( SCREEN_WIDTH / 2.f, SCREEN_HEIGHT / 2.f, 0.f );

//Red quad
glBegin( GL_QUADS );
    glColor3f( 1.f, 0.f, 0.f );
    glVertex2f( -SCREEN_WIDTH / 4.f, -SCREEN_HEIGHT / 4.f );
    glVertex2f(  SCREEN_WIDTH / 4.f, -SCREEN_HEIGHT / 4.f );
    glVertex2f(  SCREEN_WIDTH / 4.f,  SCREEN_HEIGHT / 4.f );
    glVertex2f( -SCREEN_WIDTH / 4.f,  SCREEN_HEIGHT / 4.f );
glEnd();

These all might be very silly questions and I believe they are. I think there is a problem in my understanding of how matrices work in OpenGL. It would be very nice of you to enlighten me on this matter :)

\$\endgroup\$
  • 2
    \$\begingroup\$ push and popMatrix are deprecated you should find a more recent tutorial (at least 3.0 and up) \$\endgroup\$ – ratchet freak Sep 20 '14 at 13:13
  • 1
    \$\begingroup\$ I would like to also add to ratchet freak's answer, the matrix handling is deprecated => focus on that the matrices do not how they are handled in those tutorials, it is not relevant(maybe even counter-productive) as in new OpenGL it is completely different. \$\endgroup\$ – wondra Sep 20 '14 at 13:39
0
\$\begingroup\$

There are 3 heavily used transformation matrix values, as follows

For each object in the scene, a World transform that takes vertex coordinates relative to the origin of a mesh/model and converts them to World coordinates relative to the World origin. This transform is made up of the combined Position, Orientation, and Scale of a specific object in the scene.

For each camera in the scene, a View transform that takes world coordinates and converts them into camera relative coordinates.. This transform is made up of the position and orientation of the camera/eye within the scene (it is also possible to scale here but this ability is seldom used)

And finally, for each Viewport (for most games only one, but think about modeling apps like 3DS Max etc that allow you to set up top/front/right/perspective views of the same model as an example of multiple viewports), a Projection transform that takes camera relative coordinates and translates them into "screen" coordnates (which are 2D coordinates suitable for selecting a pixel in the back buffer to be written to by your pixel shader). This transform is made up from the aspect ratio, field of view, and center of view offset of the viewport.

These three transforms, or some combination of them, get passed off to your vertex shaders so the shader can convert vertex lists in GPU memory into screen coordinates. This vertex information usually specifies triangle lists, and these triangles are clipped against the viewport. If the clipped triangle covers any pixels in the viewport, those pixels are scanned, and the pixels shader is called to generate color information for that pixel using color, uv, normals, and any other data passed in the vertex structure. All the color/uv/normal/etc data for the 3 verticies that make up the triangle being scanned are blended based on the distance of the current pixel from each of the 3 verticies. That covers the basics of vertex transformation and the rendering pipeline in modern graphics API.

As mentioned in previous comments and answers, you need to get away from the old style OpenGL techniques which were designed to support graphics cards with fixed function pipelines and no shader capability at all. You need to concentrate on things like vertex buffers, index buffers, texture buffers, and constant buffers, all of which are used to store information persistently on the GPU to be reused over and over during each rendering pass. For simpler applications where you do not have dynamic vertex/index/texture data, the rendering portion of your game loop will be little more than updating the constant buffers that the shaders use to access the transforms, telling the GPU which shader to actually use for the next draw command, and of course making the draw call that will kick off the processing of vertex data to pixel data.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.