If you’re a mechanic, people ask you about the strange sounds their car is making. If you’re a doctor, people ask you about the strange rashes and aches they find. And if you’re a programmer like me, people ask you about the stupid stuff their computer does. Unlike mechanics and doctors, people don’t ask me about this because they want me to fix it, they just want to know why the program does these silly things.
Today’s silly thing is this:
“Why does the game force me to restart when I change the graphics settings?”
I’m sure it’s happened to most of us. You change your keybindings, and the game is fine. You change your subtitle or language settings, and the game is fine. But then you change something like anisotropic filtering and suddenly the game freaks out. It either restarts itself, or it insists that you restart it before you can see the results of your changes.
Obviously this problem in unique to PC games. I’ve never seen a console game exhibit this problem. Then again, I’ve never seen a console game that had graphics settings that could be changed.
My usual disclaimer: I don’t “do” modern engines. Last year I was making a graphics engine that was – from a technological standpoint – somewhere in the ballpark of Doom 3. So my knowledge isn’t current with cutting-edge modern engines. But for the purposes of this discussion, it doesn’t matter. The problems we’re going to talk about here are sort of timeless.
Most games – by which I mean every single example of videogame source code I’ve ever seen or worked on – have an initialization phase. You launch the game, and the program spends some time getting things ready. Before you ever get a glimpse of that main menu, there are hundreds or even thousands of little tasks the game has to perform.
Some of these tasks need to be done before others. I want to initialize the input system for handling mouse input, but that system depends on the menu system. So I need to start the menu system before the input system. But the menu system depends on the font system. (Because it needs to know how big the letters and words are before it can know where to position menus and buttons.) So I need to load the font system first. But the font system depends on another thing, which depends on another thing, which depends on you get the idea.
Now, I could make my menu system dynamic and adaptable. I could make the menu system constantly check to see if the game font has changed, and if so then it will go back and re-calculate the spacing so that buttons, menus, and scrollable lists all work properly. If I do things this way, then the font can change at any time and the program will adapt seamlessly.
Except… why would I do this? I can’t remember a single game that had the font change like this. Making a dynamic interface that can handle changing fonts is a lot more work, and there’s no reason to do that work if the game doesn’t specifically call for it.
All of this applies to graphics, only moreso. In graphics, we have shaders. Shaders are special programs that run on your graphics card. It’s like an entire separate program, in a different language, that runs on a completely different timescale from the game itself. Depending on the game, it might have dozens of different shaders, each dedicated to a specific special effect. One for shadows. Another for glowing lens flares around lights. Another for softening up the jagged edges on pixels. Another for walls and other non-movable scenery. Another for animated stuff like monsters and people. Another for the “cloaking” effect when characters turn invisible. Another for making things disintegrate smoothly. Another for reflective surfaces. Another for all the stuff that’s part of your body in a first-person game. (Your character’s arms and weapon.) Another for particle effects. And so on.
Each shader has to be loaded onto the graphics card, and then the game needs to set up a little system to communicate specifically with that shader. On top of this, different shaders have different needs. Maybe a shader needs a specific texture map. Maybe a particular shader needs a particular 3D model to work properly.
This forms a hierarchy of dependency. If I turn off full-screen anti-aliasing, then suddenly the game needs a different shader. That shader needs different input textures and has a different way of talking to the game. Yes, the programmer could make the entire graphics engine dynamic and adaptable, so that these systems can change whenever you like, but that’s a lot more work. More importantly, it’s more complicated. And complicated is bad.
Before we chalk this up to programmer “laziness”, let me point out that back in 2008, developer John Carmack stood in front of NASA engineers and said that graphics programming was “far more complicated” than aerospace engineering. And keep in mind, Carmack is one of the very few people in the world who has done both professionally. Graphics programming is a dauntingly complex discipline, and it’s only gotten worse since 2008.
We really are hitting the limits of what you can reasonably expect a small group of typical programmers to accomplish. The old engineering joke / adage / truism is:
“Good, fast, cheap. Pick any two.”
The engine needs to be blazing fast. It needs to look great. Game budgets are already pushed to the limit of what publishers are willing or able to provide. Yes, you can make a graphics engine able to seamlessly swap out any shader for any other shader at any time, but that makes the engine more complex. Heck, just making a number of options can inflate the number of lines of code and shader combinations. Maybe you need a shader for light bloom, another for antialiasing, another both both, and another for neither. The number of combinations can quickly multiply out of control.
There’s more lines of code to write. More lines of code to maintain. And when a bug pops up, the search will take that much longer because the number of places it could be hiding is that much larger.
So it’s easy to see why developers might not want to spend resources on this. It’s a problem that really only applies to PC gamers, who are a minority of the customer base. Is it worth making your graphics engine drastically more complex just so a minority of your users can change graphics options without needing to restart? For a lot of developers, the answer is apparently “no”.
(Have a question for the column? Ask me!.)