We will begin our study of shader-based OpenGL with the "Hello, World" of OpenGL programs: drawing a single triangle. The output is on the right, but don't be fooled by the simplicity of the example. In this graphical version of "Hello World", we will actually see the bulk of the OpenGL concepts we will need for basic OpenGL programming.

We will study two different implementations:

Implementation 1: HelloOpenGLBasic

In this simple implementation, (nearly) all of the OpenGL code is in a single small file so that we can focus on understanding the graphics modeling and rendering process from the perspective of OpenGL.

Implementation 2: HelloOpenGLFramework

The code structure we studied in "HelloOpenGLBasic" above does not scale up to even moderately interesting scenes. Moreover, its structure makes it unnecessarily dependent on the GLFW window manager. The restructured implementation described here isolates the GLFW dependence to one part of the Controller class hierarchy and illustrates how the basic responsibilities and data are assigned to our two most basic canonical classes: ModelView and Controller.

Two Rules of Thumb

As you develop your programs using this framework, keep in mind two general Rules of Thumb when it comes to deciding how functionality should be assigned to classes you design and implement:

  1. No OpenGL function (i.e., one whose complete prefix is gl or glu) should be called from any class in the Controller hierarchy except for certain query calls (i.e., glGet*) or functions that have parameters that are pixel-based in window manager space. For example, glClear, glViewport and/or glReadPixels might be called from such a class, but not glTexImage2D, glBindVertexArray, etc.
  2. No window manager function (e.g., one whose complete prefix is glfw) should be called from any class in the ModelView hierarchy.

Finally...