Drinking from the Firehose: Learning Computer Graphics Techniques and Programming
July 7, 2020
Graphics researchers waiting in the water fountain line at SIGGRAPH Yellowstone.

Graphics researchers waiting in the water fountain line at SIGGRAPH Yellowstone.

Computer graphics as a field is broad, deep, complex, and intimidating. More than half a century of rapid progress driven by academic research and industry practices underly it. Parts delve pretty far into physics, math, signal processing, systems programming (and more). And performance is always at a premium—so simple, straightforward techniques are often not possible, and high-level programming abstractions not usable.

Despite all this—or perhaps because of it?—it’s so rewarding to get better at graphics. As a kid, what drew me to graphics (and game programming) was the promise of creating vast, beautiful, dynamic, interactive worlds from nothing, to my exact specifications, just by flipping bits in computer memory.

Besides the creative aspect, there’s also beauty in building a deeper connection to the physical world by learning how to simulate it—and in a sense rebuild it—yourself. And just knowing you can make magical things with only your hands and a keyboard is very satisfying. (Note: large, expensive GPU may also be required.)

Many graphics experts have stated they love the field’s tendency to combine the artistic with the technical and scientific. In graphics there is rarely a “right” answer, but rather thousands of tradeoffs between correctness, performance, and aesthetics. And as the field evolves—hardware improves, and new techniques build atop and replace old ones—these tradeoffs continually change.

So graphics is great, but hard. Let’s talk some more about that.

Who I Am and Who This Article Is For

I’ve recently gone through the process of diving much deeper into graphics—particularly real-time graphics—so I’m in a good place to offer advice to others who are on this journey. About six months ago I released a VR app (PARTICULATE) that I built on a custom engine over the course of several years.

I was not starting from scratch by any stretch—I’ve programmed for decades and did a significant amount of graphics work in college as a bachelor’s and master’s student (including co-authoring a SIGGRAPH 2004 paper). But I did take many years time off graphics to do other things, and I had missed a ton of progress when I came back so I had an enormous amount to learn. (And it’s not like I knew everything earlier, of course—ha!)

I’m writing this article primarily for people who’ve already started their graphics journey. If you’re an absolute beginner—which is also great!—this article will likely be an interesting read, but I’d recommend starting with one or two beginner books or tutorial series before spending too much time getting lost in the wider world of graphics.

If you are already on the path of growing your graphics knowledge, you may be feeling like you’ve bitten off more than you can chew. That’s normal. It’s common to delve into a new graphics sub-area only to be confronted by a mountain of long and dense books, journal articles, PowerPoint presentations, and PhD theses. (Perhaps you would like to quickly peruse all 432 formula-filled pages of this seminal work in path tracing? Or some light afternoon reading on physically based rendering in the Frostbite engine? (122 pages))

I’m writing this article to offer tips and advice that I’ve found helpful in the last few years. I’m focusing on general principles rather than specific resources (books, tutorials, etc.), but I will mention some of those at the end. (Because what would an article on learning graphics be without a bunch of references and links that are out-of-date or dead in a couple years? ;) )

Let’s get started.

Mindsets

First, at the risk of sounding flippant, I recommend being extremely motivated to learn more about graphics. This may sound unnecessary (or alternatively, obvious) but it’s an important factor—the more motivated you are, the more time you will put in, and the less likely you’ll be to give up when things get difficult, which they will.

It’s possible to do some quick weekend-style graphics projects (like writing a simple ray tracer using Peter Shirley’s books), but more serious projects will involve a lot of learning and grinding to make significant headway. It’d be great if things weren’t this way, but that’s been my experience.

For me, the best way to get motivated is to start building a real product that I plan to release eventually (which is what I did with PARTICULATE). Some people are happy to work on multiple small “toy” projects, or to build a personal engine to learn about different techniques. There’s nothing wrong with those approaches—and taking them may even be best for learning many techniques as quickly as possible. But I’m most obsessively motivated when I have a vision of a finished product people can use. This vision helps guide me toward what to learn and do next (and motivates me when I’m feeling discouraged). Your mileage may vary—find what works!

Second, it’s important to cultivate a tolerance to feeling dumb. It’s easy to have a simple goal (say, rendering text) turn overwhelming as you encounter an avalanche of articles, alternative approaches, unfamiliar math, and dense PPTs and PDFs. (For the example of text rendering—there’s a reason Eric Lengyel has made a business out of selling his library for high-quality text rendering to companies that already employ rendering specialists. Text rendering is way more complex than it initially appears.)

If you hate feeling dumb—and I can’t say I love it, but I’ve gotten better at tolerating it—you’re much more likely to give up and return to more familiar pastures. Being extremely motivated also helps at persevering through the pain of feeling dumb :)

It will often take multiple passes over the same material to fully understand it (or even approach that). I like to read different resources so I can absorb different explanations of the same concepts, as every author has their own angle. Further, even after multiple passes, you may still not feel like you fully understand a new topic. This is something I had to acclimate to—as a seasoned programmer I was used to feeling comfortable with new concepts in computer science fairly quickly.

Reading multiple authors' takes on the same topic is like reconstructing a 3D model from multiple images—the additional angles help fill in the full shape. (Image from this article.)

Reading multiple authors' takes on the same topic is like reconstructing a 3D model from multiple images—the additional angles help fill in the full shape. (Image from this article.)

I recommend aiming not for full understanding but rather to understand a topic a bit more each time you read a new resource on it. Look it as peeling off the layers of an onion. (I mentioned this idea in Laura Reznikov’s Twitter thread about learning graphics, which contains other good tips.)

Sometimes you will need to implement things that you feel like you don’t fully understand yet. A common example of this is typing in mathematical formulas that still seem a bit cryptic. This can be a dangerous road to go down (as it makes debugging extremely difficult, among other issues), but sometimes going into a bit of “debt” in this regard is necessary to keep things moving.

Make a list of things you’ve implemented that you don’t fully understand, and aim to learn more about them as you continue moving forward. (On a related note, this Twitter thread contains some useful tips on understanding math used in graphics papers.)

It’s really important in graphics to embrace building off the work of others. In programming more generally, it’s often possible to devise your own algorithms without doing much background research. Of course there are exceptions—better to use quicksort than reinvent bubble sort yourself—but I’ve found in some other areas it’s easier to program by the seat of your pants. You’ll waste a lot of time coming up with sub-par solutions if you try to do this a lot in graphics. As you get more experienced, you’ll be able to develop new techniques yourself, but even then you’ll be heavily relying on prior work.

Managing Information Overload

To learn graphics deeply—especially on your own or with limited supervision—you need to become a master of finding resources, combing through them quickly, and assimilating different approaches to the same problem (or even different takes on the same approach). Expect to be reading a lot of articles, blog posts, course notes, conference papers, forum posts, Twitter threads, PowerPoint presentations, PhD and Master’s theses, and books (and watching a lot of videos of conference presentations).

Paging through cryptic PowerPoint presentations—especially ones without speaker notes—is a special kind of “fun” that is sometimes necessary due to lack of videos and articles on the topic you’re interested in.

Me when trying to decode a PowerPoint presentation lacking speaker notes.

Me when trying to decode a PowerPoint presentation lacking speaker notes.

Sometimes you will waste a lot of time trying to decipher a particular resource only to figure out later that the author wasn’t explaining things well. Eventually you’ll develop a sixth sense for when a resource feels overly obtuse (even when you don’t yet understand the topic). Once you detect this, you can quickly move on to other resources on the same topic—which hopefully exist—and waste less time trying to decipher an unclear explanation.

Expect to encounter this type of scenario often: You have a new graphics problem to solve (for a project you’re working on), and you need to learn the landscape of that problem to determine how to proceed. What are the state-of-the-art solutions? What are the trade-offs between quality, efficiency, and ease-of-implementation?

Just answering these questions can take quite a while—the web is littered with older approaches that are now rarely used (stencil shadows?) and experimental approaches that never quite panned out. Then in some cases you’ll find an approach that looks great but has terrible performance (e.g., many of the takes on order-independent-transparency).

Things are so complex in part because tradeoffs change over time as graphics hardware and APIs evolve and new techniques arise. A technique like deferred rendering might be ubiquitous for a while but then start to fall out of favor as the landscape changes (new hardware shifts the tradeoff between memory bandwidth and computation; new techniques prove hard to integrate with its restrictions).

The best-case scenario is to find a “roundup”-style article by an expert—needs to be a recently-written one!—that covers the main solutions to a particular problem, with descriptions of the tradeoffs involved. Such articles unfortunately aren’t always available, but they’re invaluable when you find them. This article on text rendering by Aras Pranckevičius is a great example.

Another good option is to ask a friendly expert, particularly one who has written about the problem you’re interested in before. Twitter is a great place to do this. See who other people in graphics are following to find who’s on there.

Even if you have fully up-to-date information from an expert, you’ll still have to determine how applicable a technique is to your specific situation (API, hardware platform, quality/performance needs, etc.). The last thing you want to do is spend weeks implementating a solution only to find out that it is ill-suited to your situation.

To help with this, I recommend looking for an what I would call an “existence proof”—a game/application running on a similar platform (to your project) that solves your problem with good-enough quality and performance. Once you find such an example, try to find the specific technique(s) used by the developers. (Often they’ll have publicly discussed it in an article or presentation, or you can ask them directly.) It’s comforting knowing you’re implementing a technique that can achieve good results on your target platform. Now, actually replicating those results is another story—but you know it’s possible :)

Always Be Learning

In programming, Hofstadter’s law is a thing:

It always takes longer than you expect, even when you take into account Hofstadter’s Law.

Hofstadter's law

In a dense and complex field like graphics, this is doubly true. When starting a project or task, you don’t yet know if you’re opening a Pandora’s box. The needed solution may be much more complex than you think, and a lot of background reading may be required. For this reason, I recommend anticipating the next few problems you’ll face and starting the reading/research process before you get to them.

What’s the best way to make sure this happens? Always be learning. I recommend constantly expanding your graphics knowledge beyond what you are currently working on. It’s good to spread your learning net wide, as you never know what you’ll suddenly need to use in the future—and concepts from different areas will fit together in unexpected ways.

I adopted a daily learning practice to make sure that I’m always pushing the frontiers of my knowledge forward—every work day, I spend the first hour consuming articles (and so on) about graphics (and some non-graphics but programming-related topics). By doing this for several years straight, I’ve absorbed a massive amount of information.

I also spend some of my spare time reading longer-form books and watching videos of conference presentations and such. I recommend not trying to overdo it in your free time though, as that can lead to burnout. (I’ve had to tone things down in the past for this reason.)

When choosing how to focus your learning time, I recommend spending a disproportionate amount of time on the “fundamentals”—the things that lie at the foundation of many techniques and tend to come up over and over. Some examples of fundamentals are:

(This list focuses on real-time rendering.)

As you begin to really nail fundamentals like these, you’ll find your ability to pick up new techniques starts to accelerate. (And it’s really satisfying to notice this trend.)

I think graphics experts tend to underestimate how much time it can take to even learn the context required to process new information (because as experts they already understand the shape of the graphics landscape and how its pieces fit together). For example, to really understand what mesh shaders enable and why they’re a step forward, it’s necessary to understand a ton of context—and much of that context isn’t contained in articles about mesh shaders!

It took me a few years of dedicated learning to really feel like I had mapped out the field and turned all the “unknown unknowns” into “known unknowns” (and in some cases “known knowns” :) ). Once I had done this mapping—which took way longer than anticipated as the rabbit hole of unknown unknowns is surprisingly deep—it became far easier to assimilate new information quickly (and also to know where to look for it). When there are still many unknown unknowns, it can feel like you’re bumping around in the dark.

The feeling when there are still many unknown unknowns.

The feeling when there are still many unknown unknowns.

This is the end of my general advice on how to approach learning graphics. A final remark—remember that this journey is going to take years (and it will never finish). Once everything begins to click, though, it’s incredibly satisfying and empowering.

Resources

As mentioned, the focus of this article isn’t specific APIs, techniques, or resources—but I do want to list some of the most important resources that are of general interest. Beyond this list, there’s an extremely long tail of resources (conference papers and presentations, blog posts, etc.) that you’ll generally find by Googling to dig into specific topics.

Books

I have read and recommend these:

Real-Time Rendering and Physically Based Rendering in particular are dense tomes that can be hard to get through, but very worth it—look at it as a character-building experience, and don’t expect to fully understand everything on the first read.

I have not read these (yet), but they come highly recommended:

There are a number of books on more niche topics (and on specific rendering APIs), but I will leave the list at that.

Videos

There is a ton of top-quality content in conference presentations, though you’ll have to be somewhat selective, lest you spend the next decade doing nothing but watching videos.

Web

This list only scratches the surface. I tried to include some canonical references that come up again and again (and are unlikely to be dead links a year from now—I hope!).

Where to ask questions

Seriously though, I highly recommend using Twitter if you are going deeper into graphics, as it exposes you to some of the smartest and most accomplished people in the field. Just try to stay alert and dodge the flamethrowers.

Resource wishlist

I would love to see an intermediate-to-advanced-level book on modern real-time rendering engine architecture. I haven’t found any examples—books on game engines tend to gloss over the rendering aspect (as there are so many other things to cover), and books on rendering tend to focus on specific techniques rather than how it all fits together into a complex interconnected system. As it stands, one’s left to read scattered articles on the subject and dive into source code (Unreal Engine and Godot are two reasonable game engine source options).

I would also love to see a more-active centralized forum for graphics discussion. It seems that Twitter has largely superseded more traditional internet forums, but it’s decentralized (and chaotic) nature and confusing threading make it lacking as a full replacement. It’s also hard to have in-depth discussions on Twitter. (Discords are another good option but share some of Twitter’s issues.)

Follow me on Twitter: @miketuritzin