Procedure display is responsible for the actual drawing.
void display()
{
This line clears the buffer; the buffer is basically the memory are where the image is rendered; it is basically a matrix with width and height 600x600. To clear means to set every cell of the matrix to the same value. Every cell is a pixel and contains a color and a depth. With this call you are telling OpenGL to paint everything opaque black, and to reset the depth to 1. Why opaque black? Because of your call to glClearColor: the first three parameters are the red, green and blue component, and they can range between 0 and 1. 0,0,0 means black. For the last component you specified 1, which means opaque; 0 would be transparent. This last component is called alpha and is used when alpha blending is enabled. Why the clear depth is 1? Because 1 is the default, and you didn't call glClearDepth to override that value.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
This is telling OpenGL that you want to draw quadrilaterals.
glBegin(GL_QUADS);
You want these quadrilateral to be red (remember that the first component of a color is red).
glColor3f(1, 0, 0); // NOT SURE WHERE THIS STARTS, AND HOW THE COORDINATES WORK
Now you list the vertices of the quadrilateral (it's only one, four vertices); all vertices will be red because you never update the color by calling glColor3f; you can associate a different color to every vertex, the final result is usually very cute if you pick red (1,0,0), green (0,1,0), blue (0,0,1) and white (1,1,1); this quadrilateral should appear to screen as a square, because it is a square geometrically, your window is a square, and the camera (defined with glOrtho) has a square aspect (first four parameters of the call to glOrtho). If you didn't call glOrtho you would probably see only red, because the default OpenGL coordinates range between -1 and 1 and so you are covering the entire window.
glVertex2f(-1.0f, 1.0f);
glVertex2f( 1.0f, 1.0f);
glVertex2f( 1.0f,-1.0f);
glVertex2f(-1.0f,-1.0f);
This means that you are done with drawing.
glEnd();
Technically, it may be that OpenGL didn't send any of the commands you specified to the graphic card; commands may be enqueued for efficiency reason. Calling glFlush forces the command to be sent to the graphic card.
glFlush();
}
You wrote this function, init to initialize some of the OpenGL states, that you felt would remain stable across the application. In reality a real application like a game would have most of this stuff under display. For instance a game must continuously update the camera, as the player moves.
void init()
{
Here as we said before you are setting the clear color to be opaque black.
glClearColor(0.0, 0.0, 0.0, 1.0);
Here you are saying that the camera is not of a perspective type; basically things that are far away don't get smaller. It is similar to the view that an artificial satellite has of a city. In particular you are creating a camera which is not "centered" on the field of view: I recommend to use a call like glOrtho(-10.0, 10.0, -10.0, 10.0, -1.0, 1.0) for your first experiments. For a non perspective camera the coordinates that you specify here override the convention -1 to +1 that we mentioned above. Try to regulate the parameters such that your red square appears small, and centered.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 10.0, 0, 10.0, -1.0, 1.0); //What does this do and how does it's coordinates work?
Here you are basically positioning the camera relative to the square, or the square relative to the camera; there are infinite ways to see it. You are defining a geometrical transformation, and the reason why it is called MODELVIEW is that it is not uniquely something that alters the model (the square) or the view (the camera) but both, depending on the way you see it. However, your square appears rotated because you are calling glRotatef; remove it and the square should appear like a square.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glRotatef(30.0, 1.0, 1.0, 1.0);
Depth test is a technique that uses the depth store in the buffer in order to remove hidden surfaces, for instance the back faces of a cube in a 3D scene. Your scene is 2D and you are drawing only a quad, so this is really non affecting your drawing.
glEnable(GL_DEPTH_TEST);
}
In the main you are interacting with glut, an optional subsystem which is not part of OpenGL but is useful to carry out some boring and tedious operations that only the operating system is authorized to perform.
int main(int argc, char *argv[])
{
First you must init glut.
glutInit(&argc, argv);
Then you define the window that will contain your rendering image.
glutInitWindowSize(600, 600);
glutInitWindowPosition(250, 250);
GLUT_RGB means that your window only supports red, green and blue, and doesn't have an alpha channel (this is very often the case). GLUT_DEPTH means that your buffer will be able to store the depth of each pixel. GLUT_SINGLE means that the window is single buffered, that is your commands will directly draw on the window; another option is double buffering, where you actually draw on a back buffer, and then you swap front and back buffer so that the rendered image appears suddenly, and not in a progressive fashion. Your scene is so simple that you shouldn't notice any difference between GLUT_SINGLE and GLUT_DOUBLE.
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
Then you actually create the window.
glutCreateWindow("Model View");
You tell glut which function should be called to render the scene.
glutDisplayFunc(display);
Here you call your init function.
init();
This is a window loop, provided by glut. Most windowing system require a software loop in order to keep the window alive, and able to respond to clicks, drags, resize and keyboard strokes.
glutMainLoop();
return 0;
}
Long story short, several versions of OpenGL are available, and they can be programmed using several languages, and targeted to several platforms. The single most important difference between these versions is that some use a fixed function pipeline (FFP) whereas the newest versions have a programmable pipeline. Your program uses a fixed function pipeline. You should switch to a programmable pipeline whenever you can, because it is the modern way of doing computer graphics, and is much more flexible, even though it requires a little more programming, as the name suggests.
You should ignore the tutorials that I linked originally, I didn't immediately realized how outdated they were. You should go with the one recommended by datenwolf or, if you are interested in mobile development, you could consider learning OpenGL ES 2 (the 2 is important, because the previous version was fixed function). There is also a variant of OpenGL ES 2 for HTML5 and Javascript, called WebGL. You find the tutorials here, together with a ZIP file containing all the examples; I use their codebase whenever I need to check if I understood a new concept.