This code is useful for programmers working with a new device (such as a virtual reality head mounted display: VR HMD) for the first time, or for programmers working with hardware graphics at all for the first time. I also use it as a testbed for eliminating large libraries when creating minimal reproducible cases for bug reports.
The program runs under Windows, Linux, and OS X. I include a Visual Studio 2015 project file. If you enable VR rendering, it supports Oculus Rift, DK2, HTC Vive (Valve's HMD, in developer kit, "Pre", and consumer editions).
Reference CodeMy OpenGL + OpenVR reference code is available through subversion:
and can also be directly viewed in a web browser. This code kept continuously up to date as underlying APIs change. The sample code covers examples of the major 3D graphics features in about 400 lines:
- Window, OpenGL, HMD, and OpenGL extension initialization
- Triangle mesh rendering (OpenGL Vertex Array Buffers)
- Shader loading, compilation, and argument passing (OpenGL Program, Shader, and Uniform Buffer Objects)
- Offscreen rendering (OpenGL Framebuffer Objects)
- Materials and image file loading (OpenGL Texture and Sampler Objects)
- Ray tracing (including ray setup compatible with rasterization)
- Procedural texturing
- A tiny vector math library
- Basic keyboard and mouse handling for a free-flying camera
- Virtual reality tracking and rendering (OpenVR)
I use no libraries for the main object setup and rendering, except of course for OpenGL itself. This avoids dependencies and exposes the core OpenGL calls.
There are a lot of other OpenGL sample programs on the web, but most either have heavy library dependencies or are written for previous versions of OpenGL and are now obsolete. Likewise, OpenVR's own "hellovr" program includes a large demo infrastructure that obscures the key calls. I intend this minimal example to be something that is easy to plug into your preferred rendering engine.
OS CommunicationOpenGL only handles rendering. Window creation, copying images to the window, and event handling must be done in a platform-specific manner. I use three standard, slim, and multiplatform libraries to abstract that piece and put the code interacting with them into two headers (minimalOpenGL.h and minimalOpenVR.h):
- GLFW for window creation and events
- GLEW for OpenGL extension loading
- OpenVR for HMD initialization and tracking events, plus SteamVR's runtime
If you're working with G3D, those are already installed on your system. If not, then you need to download the headers and binaries or source. No "installation" of these libraries is needed, except for running SteamVR under Steam if you wish to render in VR.
Matrix MathI provide a very small matrix and vector header file, matrix.h. I specifically wrote the minimalOpenGL.h and minimalOpenVR.h files so as to not depend on this header, since you'll probably want to use some more full-featured library.
I therefore pass all matrices and vectors as raw float pointers, using row-major conventions for matrices.
Other APIsThe sample code is OpenGL 4.1 because that is the latest version that runs across Windows, Linux, OS X, and SteamOS. (The latest OpenGL is 4.5, but Apple does not support it on their platforms). WebGL and OpenGL ES are similar APIs that lag OpenGL's feature set by a year or two and run natively for web browsers and mobile.
Some alternative hardware graphics APIs are DirectX12 (Microsoft's platforms only), Vulkan (very low level, no Apple platforms), and Metal (Apple's platforms only). Sony and Nintendo gaming platforms have their own proprietary APIs that are similar to OpenGL/DirectX.
Other Minimal ContextsThe procedural sky in my example is based on fractal code by Inigo Quilez. The shadertoy website is full of great procedural ray tracing examples by him and others that can easily be inserted into the context of my sample code to run as a native binary.
Sean Barrett maintains a set of single-header libraries for common graphics tasks, such as loading multiple image file formats and voxel rendering.
The native file dialog library is essentially a single file for each platform.
The SDL library is an alternative to GLEW + GLFW. It is slightly more heavyweight because it supports audio, Android, and DirectX as well.
Working with an EngineOnce you're comfortable with OpenGL, you'll probably never want to write code that directly uses it again. Most programmers use an abstraction layer so that they can work at a higher level, for example, working with "meshes" and "materials" instead of "vertex array buffer objects" and "texture and sampler objects"...and with tools for profiling, debugging, and error checking.
The G3D Innovation Engine is my open source abstraction intended for research, prototyping, and education on Windows, Linux, and OS X. Its strength is ease of experimentation. The Unreal Engine, Unity Engine, and Lumberyard are commercial game engines that have no cost for basic use. Their strengths are tools, content, and mobile and console platform support.
Thanks to NVIDIA, Oculus, and Valve for supporting my real-time graphics work at Williams College through funding and hardware gifts!
Morgan McGuire (@morgan3d) is a professor at Williams College, a researcher at NVIDIA, and a professional game developer. His most recent games are Project Rocket Golfing for iOS and Skylanders: Superchargers for consoles. He is the author of the Graphics Codex, an essential reference for computer graphics now available in iOS and Web Editions.