Skip to content

Instantly share code, notes, and snippets.

@romanlarionov
Last active June 5, 2023 07:29
Show Gist options
  • Star 86 You must be signed in to star a gist
  • Fork 9 You must be signed in to fork a gist
  • Save romanlarionov/2a22e77be3f2b574a2bd to your computer and use it in GitHub Desktop.
Save romanlarionov/2a22e77be3f2b574a2bd to your computer and use it in GitHub Desktop.
OpenGL Startup

Travel Guide to OpenGL

I've figured out several things while trying to extend my knowledge of Computer Graphics.

  1. OpenGL can be a bitch if you don't know what you're doing.
  2. There is no worse pain than to experience CMake without knowing what you're doing.
  3. When walking to the depths of hell, it would be nice to have a travel guide.

And that's what this is, a travel guide.

Preface

This article resonates with me more and more over time. My advice for anyone aspiring to program graphics profesionally is to redirect their focus towards this tutorial. While OpenGL is great, learning it is not necessary to understanding graphics. You can make compelling images using relatively simple tools. I think OpenGL is ultimately easier to learn by starting from the absolute fundamentals.

But at the same time, do what you think is fun!

History

OpenGL is an attempt by a group of people known as Khronos to make a cross-platform API for graphics processing units (GPUs). Khronos isn't really a company, but rather a consortium of various people/companies that mutually vote/collaborate on how APIs like this should be designed. They have many more APIs and file formats than just OpenGL that each handle something else related to heterogeneous processing.

It is up to the various platforms that OpenGL can be run on to perform that implementation. Thus you have a different implementation of OpenGL (with the same interface) from each independent hardware vendor (IHV) for most operating systems.

OpenGL is old. Many consider it too old and too bloated. It was initially designed in the early 90s before GPUs were even a thing. It has evolved over the years to make better use of graphics hardware, but still suffers in some ways (on the driver level) of exposing sub-optimal coding paradigms. Look into Vulkan[1, 2] if you're curious as to why this is. While vulkan is cool and new, I wouldn't blindly tell a beginner to jump straight into it. OpenGL is still alive and being used by many sources. I still personally believe it can be a good introduction to graphics programming.

Programming Languages

OpenGL has been ported to many languages. Everything from Python to Haskell has an interface to the API. Javascript is becoming a popular language for 3D graphics through WebGL and Three.js.

I am going to assume for the remainder of the document that you will be using C++, as is common in the world of high performance graphics.

System

Each OS has its quirks.

  • Apple has depricated OpenGL. They're really pushing support for their own graphics API called Metal.

  • OpenGL works just fine on Windows, but Microsoft also designs an alternative which is exlusive to Windows and XBox called Direct3D.

  • Mobile platforms have a forked subset of OpenGL called OpenGL ES.

The OpenGL Stack

As stated above, OpenGL is an interface to graphics acceleration hardware. It might seem weird at first that you can't just write regular C++ that runs on your GPU. After all, it just works on the CPU. What's so different? Why can't there be a compiler that turns C++ into whatever ISA runs on my GPU? Well outside of things like SYCL, this isn't a trivial thing to do.

You might also wonder why you can't use something like CUDA to write graphics applications. And you most certainly could. The issue is that tools like CUDA actually take significatly simpler paths through the GPU pipeline. You won't have access to graphics-specific fixed-function hardware. In other words, there are special acceleration tools that were designed to perform real-time graphics super fast that are only exposed via graphics APIs, such as OpenGL.

For now, I'll set aside the fact that it would probably take several years of practice for a beginner to fully appreciate the difference between CPU & GPU programming. In short it is a consequence of the programming model behind GPUs, historical factors, a need to be general enough to work well for different hardware companies, and chicken-and-egg interactions between software & hardware companies.

I can see how that can be somewhat unsatisfying. OpenGL exposes an API that can seem extremely opaque and nonsensical if you don't understand what its doing under the covers. I like to think of OpenGL as a series of layers. The pure C functions are the top of the stack (what you interact with), followed by the "driver", followed by command packets or GPU machine code in command queues, followed by the hardware itself.

The OpenGL driver is a notoriously giant piece of code. I know because I've contributed to one first-hand. Drivers act as an interface between applications and hardware. They have many responsibilities. To name a few:

  • binding resources like textures/buffers. i.e. making data accessible to a shader during its execution.
  • managing the construction & submission of command packets, which are sorta like the language the GPU speaks.
  • synchronizing the various programs which run alongside one another
  • error checking and validating the commands being submitted to prevent things from completely crashing.
  • glsl compiler which converts high-level shaders into an instruction set that your GPU can execute.
  • much much more

The driver is more-or-less an arbiter between your intent and the image displayed on your monitor. To fully appreciate how much it does I would suggest working at your favorite IHV. But building (simple) applications shouldn't require much more information than what's written above.

Making/Building

OpenGL projects usually involve slightly complicated compilation processes. This is primarily because most projects include multiple external libraries to aid in handling boilerplate code. You can go the route of writing your own platform-dependant Makefiles, but that tends to get unwieldy.

An alternative that is used by many (including major game/hardware companies) is CMake.

The proper way to build your project would be to create a CMakeLists.txt file and go from there. If you don't understand the CMake language at first (don't be ashamed, its awful) and just want to get into the C++, you can simply compile through the terminal until your project gets unwieldy. At that point, you're going to have to switch.

From personal experience, I would recommend not dealing with CMake all too much. You can waste weeks trying to get your build just right and have nothing to show for it. Focus on the code.

You can start by following (or stealing) something like Glitter. Their CMake system is simple enough to get you going.

Libraries

There are many libraries that one can include to their OpenGL project to make their life easier. Here is a list of popular ones that plenty of people on the internet frequently suggest.

This is a C library with an interface for window management and input. This is basically a requirement. Without this library, there would be no way to see the output of all of your code. This ain't no WebGL, we don't got no canvas element.

With that being said, GLFW is fairly easy to set up with CMake. You can follow this tutorial and add that to your CMakeLists.txt or you can just use Glitter's.

This is an alternative to GLFW and the decision between the two is mostly up to preference. SDL does A LOT of heavy lifting. It is a very specific way of writing graphics with its own best practices. If you are interested in getting past a lot of the graphics API code and seeing something on the display, then this is a good way to go.

You're gonna need a matrix library of some sort. This is a common one that many recommend. It is a C++ header library and as such, does not need to be compiled.

If you look at the Glitter CMakeLists.txt file, you'll notice that GLM is not added as a subdirectory to be compiled via add_subdirectory(). This is because GLM is a header only library (no .cpp files) and as such only needs to be include through include_directories().

See comment below about GLAD.

This another list of header only files. Many are helpful for things you might find yourself doing, such as loading textures or generating noise.

This is a hefty library which is useful for loading 3D geometry.

Getting Started

I often found it annoying to get up and running with an idea or an experiement I wanted to perform when I was first starting out. Setting up the dependencies and patching together a CMake file desolves all creative juices.

If you want something small and simple for just those scenarios, here are a couple of files that can help: opengl.cpp

The two files above assume you've downloaded both the GLFW and GLAD source and placed them into a directory called "deps".

Resources

I don't plan on this being a full graphics course. There are a ton of other people that have put an incredible amount of time and energy into doing this already. When I was starting out, it was hard for me to filter the good from the bad resources.. How do you know if something is poorly worded if you're just starting out?

Here are a collection of links that I've found over several years that have proven useful resources (some more than others). These are basically what I have in my /Developer/Graphics/ bookmarks bar:

OpenGL Specific

Game Engine Architecture

  • Stingray Engine Walkthrough - Walkthrough of the Stingray Game Engine (now defunct) by a core engineer that worked at Autodesk.
  • Our Machinery - Blog series from the former creators of Stingray, talking about various issues/solutions they had while creating a new high-end game engine
  • Unreal Engine 4 Architecture Tutorials - Series of slides walking through various aspects of how UE4 is designed including graphics.

General Graphics Theory

Graphics Relevant Math

3D Assets

Books

Although physical books are not necessary, and can get pretty expensive, I'll list some here for the interested.

Ending Thoughts

This is by no means comprehensive. I will be updating this periodically once I have acquired a greater understanding of what it is that I'm actually doing. Until then...

@kumihoclub
Copy link

An alternative to GLEW would be GLAD, which simply generates an OGL binder header for you based on parameters you define. As a matter of fact if you look in GLFW github sources, you will find them using GLAD (As well as a Vulkan header). You can load GLAD just using the loader function built into GLFW and you are good to go. One concept i had was creating a glad file for Nvidia, AMD, and etc extensions and using macros to define which ones to use when detected the GPU hardware vender, but i never put it into affect because for my small projects using a glad file that only binded the standard ADB extensions was enough.

Also if you wanted to go for easier, then SDL would have been a better choice, its just SDL has a lot more stuff already done for you so when you use SDL it feels more like you are making an "SDL application" rather than "An application that makes use of SDL". GLFW would be better suited if you wanted to have more control of your subsystems (Good example is memory management, i moved away from SDL because it was killing my OCD that while i spent weeks writing my own memory allocators and manager, SDL was still doing its own dynamic allocations.) because it does a lot less for you and therefore gives you more control over how your subsystems are handled. There is also SFML and Allegro, but i dont like their use of OpenAL as the main dependency for their audio functionality.

Also you stated that GLFW is a requirement, it isn't, it just saves you the time required to create platform specific window contexts and input controllers.

I also have began using Clion in an attempt to migrate away from VS (and as a result, VC++ compiler mentality), i feel your Cmake pain.

@romanlarionov
Copy link
Author

Sorry for late response. Apparently I turned off the setting to receive gist notification..

I knew that about SDL, I must have just gotten lazy writing that part down. I should have more time to work on this over the summer, so I'll add in all of your suggestions in the main post.

btw. I would still argue that VS has a way shittier dependency control system than standard cmake, but it does still suck. I've been using cmake for over a year at this point and I still have trouble with it sometimes.

@adprocas
Copy link

adprocas commented Apr 5, 2017

This is a great outline. Thank you for the information. I think this will get me on the right track.

@romanlarionov
Copy link
Author

@adprocas Thanks. I just recently noticed your comment and was inspired to update it a little. Check it out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment