We are going to consider basic setup and buffers, and matrix modes. There are several buffers in OpenGL: The front buffer into which you can draw, the back buffer into which you often draw, in order that you can have a complete drawing before swapping into the front buffer; left and right buffers, which are used for stereo, that are often useful in the context of virtual reality, as well as the depth, or the z buffer. We also have other buffers, such as accumulation buffer to add up contributions, or the stencil buffer. When you draw in OpenGL, you write to some buffer. Usually, this is the front buffer for drawing as well as the depth buffer. The depth buffer is used to determine which objects are in front of which other objects, so you can have correct visibility computations. Often, we will do something known as double buffering, where you actually write to the back buffer. And once you have drawn the scene, you swap with the front buffer. Note that buffers are also used for vertices, to get information about the vertices and the geometry in the scene. In fact, we will be using buffer arrays for our drawing, which is very important in modern OpenGL. Note that there are no window system interactions built into openGL for portability reasons. However, you can use a number of windowing toolkits. In this course, we will be using GLUT. There is an equivalent version known as freeGlUT. But there are also other toolkits such as Motif, GLX and Tcl/TK. The interaction with the mouse, with the keyboard, with the Window system is implemented as callback functions which call user defined functions to interact with when a mouse button is clicked or when a keyboard key is pressed. I will first discuss some very basic setup code. You will likely want to copy this in your own OpenGL programs. We do make available the entire source code on a variety of different systems for the program that I will be showing. Note that different operating systems differ slightly. The program starts as usual in a C++ program with the main routine. The first line is the initialization or glutInit to start the windowing toolkit GLUT. The line after that, which discusses the glutInitDisplayMode, requests the types of buffers that you want from glut. In this case we will have glut single buffer, which means we just have the front buffer. And GLUT_RGB says that the front buffer is just a color buffer with red, green, and blue. I will omit this GLUT_3_2_CORE_PROFILE which is required for Apple and Mac OS to run modern openGL. You init a window. You set it at the correct position. You create the window with the appropriate title. On Windows systems and Linux systems, you need this glewInit() which just gets certain functions and wrappers initialized. Finally, we initialize the program. On the next slide I'm going to show you callbacks and functions for that. We have defined a number of different callbacks. Note that glutDisplayFunc is a callback for the display, which displays the scene. The reshape function will reshape the window if you try to change the size of the window. The keyboard function responds to keyboard clicks. The mouse function responds to action with the mouse and in fact there is also this motion function which responds to dragging the mouse. After you've defined these callback functions, you can go into the main loop of the glut program, which starts the main code. What that does is that it just listens for events that the user does such as clicking a key on the keyboard, moving the mouse, and then calls the appropriate callback function. If the user wants to redisplay the scene, you'll see that there is a command called glutPostRedisplay() which queues up the display callback. Finally I have this command deleteBuffers(), which is my own function that terminates and deletes vertex buffers that were not used that we no longer need. And finally I return from the program. We'll now talk about matrices and matrix modes. We are inspired in this case by old OpenGL. However I want to point out that old OpenGL is no longer taught in this course and it is deprecated. So what I'm going to talk about now is really only a best practice. It is not required in OpenGL. You can set up viewing however you wish. And you could in fact do your own completely different thing. But I believe this is still the best way to develop viewing consistent with how it used to be done in old OpenGL. Viewing consists of two main parts. First you need to position the objects correctly in the scene. This in itself has two components. First is the model transformation. You have the object in certain canonical coordinates. And now you want to translate it, you want to rotate it, you want to scale it to position it correctly in the world. You also have the view transformation which depends on where the camera is located and what orientation the camera has so that it can view the objects in the scene. Taken together, these are known as the modelview transformation matrix. The second aspect is what is known as the projection operation or the projection transformation matrix, where you take this 3D world, and you have to project it based on the camera onto a 2D image. In old OpenGL, which we no longer support or teach in this version of CSE 167x, these transformations were implemented with two matrix stacks. The first was known as GL_MODEL_VIEW matrix. In a sense, it would implement the gluLookAt command that we talked about earlier in the transformations and viewing lectures. Similarly, the projection matrix, GL_PROJECTION_MATRIX would implement the gluPerspective command. You would be able to push and pop matrices onto these stacks. In modern OpenGL we no longer have these modelview and projection matrix openGL labels, nor do we have their stacks. However we can still use much of the same terminology. We simply use the C++ standard template library to make stacks as needed. In fact in your homework 2 you will be defining this stack with the template, in this case, mat4. There is a 4 by 4 matrix for modelview, and you initialize it to the identity. That's what push of mat4(1.0) says. Many of the functions in old OpenGL that have been deprecated are substituted with this GLM library, which replaces many deprecated commands. The GLM library includes 4x4 matrices or mat4. I want to say a few more words about the convention that has been used in old openGL and that we will continue to use in this course. The camera is assumed to always be at the origin pointing in the -Z direction. Of course this does not mean you cannot define your camera in world coordinates as somewhere else, pointing in some interesting location in the scene. But the modelview transformation matrix will transform the scene so that effectively the camera is at the origin pointing down the -Z axis. Conceptually the objects are moved relative to this camera, which is always the origin pointing down. Therefore the modelview transformation acts on objects. I also want to note some implementation details. In old openGL, matrices are column major rather than row major. Furthermore, if you multiply a matrix it right multiplies the top of the stack. What that means is that the last command in code is the first one actually applied to the object. In the new GLM implementations, it is similar. GLM is column major and you should read the assignment notes and the documentation in terms of how to use it. Let me show you some of the basic initialization code for viewing. What I have on top are a few include lines. We've included glut and the standard library. We have a couple of commands for the mouse motion. We have the location of the eye, which is initially at (0,-2,2). We have defined two 4x4 matrices for the projection and modelview matrices. This abbreviation mv stands for modelview in the comment and p stands for projection. The combination is often referred to as mvp. In the init routine, we first a set a clearing color, which in this case is just black. And then we initialize certain values. The projection matrix is originally initialized to the identity so mat4 with 1, just puts ones along the main diagonal. That's the identity 4x4 matrix. Thereafter we initialize the modelview matrix with the GLM lookat command which is the GLM equivalent of the deprecated openGL gluLookAt command. It takes the eye location. Remember that this is set now to (0,-2,2). It takes [as input] the lookat location. The camera is looking at the origin. And it takes an up vector. Note the up vector does not need to be normalized or does not need to be to orthogonalized to anything. The GLM lookAt command will automatically create an orthogonal coordinate frame and set up the camera transformation appropriately. In the next segment, we will continue talking about the initialization routine, and also the setup for the geometry and the shader.