♦
![]() |
Now that you have studied and understand the basic geometry creation and rendering process from OpenGL's perspective, we will introduce a software architecture that is much more amenable to creating and interacting with non-trivial scenes. We have re-packaged our "Hello, OpenGL" program in the MVC design pattern we will use throughout this course. You will see here the bulk of the control and communication patterns involving the Controller and the ModelView, so be sure you completely understand all aspects of this version of "Hello, OpenGL".
More advanced programs will be impenetrable if you don't understand the execution model and code presented here.
The vertex and fragment shaders (hello.vsh and hello.fsh) are
unchanged. Functionality has been moved from hello.c++ to the Controller
and
ModelView
classes as dictated by their respective responsibilities. This restructuring
is illustrated here and explained below:
class Controller
;class ModelView
;class Controller
, although
– as you should expect – the actual model
rendering portion of its responsibilities are implemented in a method of
class ModelView
, namely ModelView::render.While studying this implementation, you will want to refer to this view of the Hello, OpenGL Execution Model.
Controller
Controller
is responsible for one-time initialization of the window manager
and creating the OpenGL Rendering Context (RC) for each
window created.
Therefore the one-time call to glfwInit has been moved to the Controller
constructor, createWindowAndRC is a Controller
method, and the previously
global variable theWindow is now a Controller
instance variable.
Class Controller
also maintains a list of current ModelView
instances. In this simple example, there is of course only one. The Controller
traverses this list whenever it needs to pass relevant event information to the
ModelView
objects it manages. In this example, it does so only when updating the display in instance
method handleDisplay.
ModelView
ModelView
instance is responsible for creating the
VAOs
and VBOs it needs to specify the geometry and attributes of
the instance. Since this is done when the instance is first created,
ModelView::initModelGeometry is called from the constructor. The previously global
variables vao and vbo are now
ModelView
instance variables.
You can download the full source code for this example from the following link: HelloOpenGLFramework_SourceCode.tar.gz. After downloading, go to the directory containing the downloaded file and do:
gunzip HelloOpenGLFramework_SourceCode.tar.gz tar -xpvf HelloOpenGLFramework_SourceCode.tar cd HelloOpenGLFramework_SourceCode make ./hello
NOTE: You may wish to use this code as a simple way to verify that you are able to build and run OpenGL programs and/or to see how simple changes to the code affect the results. However, do not use this code as a basis for general development of OpenGL code for this course. The directory structure we will see when studying the remaining example programs on this site is much better because it scales to larger programs more smoothly.
Studying this simple example program provides a good opportunity to become acquainted with important server-side
memory management issues. The analogy when writing
C++ programs is the way we use new and delete
to allocate and deallocate
heap memory. The rule of thumb is that whenever we use new, we must have a plan
for who issues the matching delete, and when they are to do it.
In a similar manner, storage for VAOs and VBOs is dynamically allocated on the GPU,
and a
similar rule of thumb applies. When calling glGenVertexArrays,
glGenBuffers, and glBufferData (all of which dynamically allocate
server-side memory), we need to know how and when to delete them.
We use glDeleteVertexArrays and glDeleteBuffers to do the
actual deletion, so the question is: when do we call them?
In an example such as this, we want the buffer to survive until the ModelView
instance is deleted. Notice, therefore, that we issue the deletion calls in the
ModelView
destructor. This will generally be our pattern.
See this advanced note related to vertex attribute arrays, especially if you use Java bindings to OpenGL.