I've figured out several things while trying to extend my knowledge of Computer Graphics.
- OpenGL can be a bitch if you don't know what you're doing.
- There is no worse pain than to experience CMake without knowing what you're doing.
- 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.
I found this article really informative and eye-opening. I recommend reading it if you're really into the idea of writing graphics seriously.
Now if you read that and would like to take that advice seriously, then do yourself a favor and follow this guide instead of reading this document. While OpenGL is great, learning it is not necessary to understanding graphics. You will understand more of what OpenGL allows you to do (and what its doing under the covers) by avoiding it altogether. Or at least until you've fully gone through the motions without any crutches.
I can only imagine how good I would be if I had done this myself...
OpenGL is an attempt by a group of people known as Khronos to make a cross-platform API for graphics acceleration hardware (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 when GPUs weren't 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.
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.
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 and web platforms have a forked subset of OpenGL called OpenGL ES.
This is really subjective. I'll list a few that I think are of note.
- Visual Studio. An amazing IDE for C++. IMO the best. A good reason to develop on Windows.
- CLion. It works pretty well if you're on Unix-like platform and acts as an alternative to Visual Studio.
- Nothing beats Vim/Emacs. Beware. This is a rabbit hole.
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 advanced college-level courses 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 worked on one first-hand. It acts as an interface between applications and hardware. Any texture that needs memory allocation, any commands that need to be translated to GPU machine code, and any error-checking (to avoid your GPU completely crashing) is handled at this level. It even comes with a built-in glsl compiler that translates your shader code to command packets (at runtime). It is more-or-less an arbiter between your intent and the image that is 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.
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.
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.
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".
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:
- learnopengl.com - probably the best single resource for getting started. With great examples and explanations.
- ogldev.atspace.co.uk - similar to learnopengl.com.
- ogl-samples - a bunch of small examples showcasing single features of the OpenGL spec.
- GLSL Sandbox - online glsl shader examples.
- ShaderToy - similar to GLSL Sandbox.
- The Book of Shaders - great examples of glsl.
- 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.
- Graphics Codex - an amazing resource that delves deep into the hardcore stuff, while keeping things simple/approachable. I frequently revisit this for review/reference.
- Sun & Black Cat - great articles by an experienced graphics dev.
- The Danger Zone - advanced articles by Matt Pettineo from Ready At Dawn.
- General Graphics/Advanced Algorithms - advanced articles by Inigo Quilez.
- GPU Gems - basically a book chocked full of advanced algorithms for realistic/efficient rendering.
- Coding Labs - Good intros to basic physically-based rendering.
- BRDF Visualizer
- Intro To Graphics (Stanford 07) - keeps things simple (really simple) and delves into the backend of rasterization-based rendering.
- Intro To Graphics (Berkeley 17)
- Intro To Graphics (Uppsala 05)
- Advanced Graphics (Utrecht 15)
- Intro To Graphics YouTube (UC Davis) - great youtube series that's basically a graduate level graphics course.
- The Essence of Linear Algebra - wonderful video tutorial on linear algebra from 3Blue1Brown
- Khan Academy Linear Algebra - great overview of 90% of the math you'll need.
- Linear Algebra Explained In Four Pages - exactly that.
- McGuire - probably the most cohesive set of classic test models available. Not all are guaranteed to be royalty free
- 3D Models - few high quality royalty free models.
- ORCA - Nvidia Open Research Content Archive
- 3DRender.com - Professional-grade models from Pixar tech director Jeremy Birn
- ten-thousand-models - generated test models used mainly by researchers
- Stanford 3D Scanning Repository - domain of commonly used test models
- Light Probes - Cube maps
- HDR Skyboxes
- Benchmarking Scenes - Standardized benchmarking scenes for rendering
- Texture Haven - High quality (free) textures
Although physical books are not necessary, and can get pretty expensive, I'll list some here for the interested.
- Real-Time Rendering - brushes over virtually every aspect of what constitutes "computer graphics".
- Linear Algebra Done Right - probably the best book on the subject.
- Ray Tracing In One Weekend - not really related to real-time rendering, but fantastic nonetheless.
- Game Engine Architecture - overview of all the various subsystems that are found within modern 3D game engines.
- Physically Based Rendering - not real time either, but still good. Thick...
- Foundations of Game Engine Development, Vol 1: Mathematics - haven't personally read, but hear is great.
- Advanced Global Illumination - haven't personally read, but hear is great.
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...