> All problems in computer science can be solved by another level of indirection
> ...except for the problem of too many layers of indirection.
It was my second year of university, and I was spending my spare time creating an off-road car racer. I started off with a procedural heightmap generator (based on good old Perlin noise), some texture blending, volumetric fog and water with reflections and refractions. This was all the rage back in 2004!
The next step was adding a car - and here is where my trouble started. Before modeling a pretty car I started with something simpler: a box. I coded up a simple red box and dropped it into the terrain. I launched the game, but the box where nowhere to be found. I had dropped it in the middle of the terrain so I could more easily spot it (it was after all a small box in a large, random terrain) - but I couldn't find it.
The thing about graphics programming is that it can be quite tricky to find the source of a bug. You can't attach a debugger to a pixel shader (not back in 2004 anyway), nor can you log what is happening. What this leaves you is tinkering: playing around with parameters until you find something that has an effect, and then try to reason logically from there.
After eyeing my code carefully I started playing around with a few parameters. At one point I changed the color of the box to white, relaunched the game (I didn't have hot-reloading) and - there it was! A nice little box sitting in the landscape. Finally I was getting somewhere! Maybe I was mixing up my red, green and blue channels with the alpha (opacity) channel? I checked the code again, but found nothing wrong. I changed the color to blue, and the box was again visible. I changed it back to red, and it was gone.
This was weird. Why would the box only be visible when it has a certain color? I checked the pixel shader. I checked the render modes. I even checked the stencil settings. Everything seemed OK - but why was my box invisible when it was red? And only when it was red? I could find it when it was blue, white, black and purple.
I tried resetting the color to red again and - WTH!? - there it was! I was back where I started code-wise, but now the box was visible again. I looked away from the screen stunned. When I looked back again, the box was gone. Then it wasn't. And then it was. And then I was enlightened.
The box had been there all along. You see, the bug was not in the software. The bug wasn't even in the hardware. The bug was in wetware. As it turned out, the reason I couldn't see the red box in the green landscape was simple: I am red-green color blind.
Handling text is an important part of every programmers life, and there are many subtleties to it. Lately I have started to realize that all text I handle in my everyday work falls into three categories:
I think we as programmers can make our lives much simpler if we decide to stick to these three categories, and to all agree on their character sets and encodings.Read More
This article describes the many design decisions that go into creating a fast, general-purpose hash table. It culminates with a benchmark between my own emilib::HashSet and C++11's std::unordered_set. If you are interested in hash tables and designing one yourself (no matter which language you are programming in), this article might be for you.Read More
In games it is very common to have scripted sequences - for instance, a piece of dialogue or a cutscene. I don’t mean these sequences are written in a scripting language (though they might), but that they follow a script like a play or a movie does. Of course, contrary to a movie script in a game the script may have some conditional branches (an NPC only saying something if the player choses to ask a certain question, for instance).
Expressing such a sequence in code should be straight-forward – after all, computer code is very much like a script. However, these scripts are often span minutes and happen while a bunch of other things are also happening. The now obvious solution to this is to put these in a separate thread - but now you open yourself up to race conditions and other nasty thread-related bugs. So what to do?Read More
Often a crash is the result of unexpected data. For instance, a crash could be caused by an extra space at the end of a string, or an integer being negative when your code didn't expect it to be. Or maybe the crash happened during the processing of a bunch of files and you want to know the name of the file that caused the crash. What you really want is the ability to inspect the values of arguments and locals at different parts of the stack. But how can we write that data to a log file on a crash without writing it when there is no crash?Read More
It was early 2014, and I was working at Arrowhead Game Studios on our reboot of the classic arcade game Gauntlet. It was the week before we where going to present our game to the world for the very first time. We where going to let the public play a select level from the game, and over the last weeks the team had been busy fixing bugs, refining gameplay and tuning the visuals. It was looking good, but during the last week something happened: the frame rate dropped from the desired 60 FPS to a crawling 20-25 FPS. Panic! What had gone wrong? And did we have time to fix it?Read More
Let say you have a set of n points in 3D and want to fit a plane to them. In this article I will derive a simple, numerically stable method and give you the source code for it. Sounds like fun? Let's go!Read More
When I started working at Arrowhead Game Studios a little over a year ago, I came from over a decade of using statically typed languages, the main one being C++. At Arrowhead we wrote most of our game code in Lua, which is a small but sweet scripting language. In this article I will summarize the main lessons I've learned, and how scripting languages in general, and Lua in particular, related to statically typed, compiled languages such as C++.Read More
Let's say you have a system of resources and you identify them using integers. These integers are meaningless to the user, but internally they may be indices into an array, or just a running count. How can we provide type-safety and make sure the user does not mix up identifiers of different types?Read More
In part one I measured the overhead of a random memory access and found it to be roughly O(√N). In part two I investigated the theoretical limit for RAM and found it to be O(√N). Together, these two articles should convince you that it's time to start thinking differently about RAM.Read More
If you have studied computing science, then you know how to do complexity analysis. You’ll know that iterating through a linked list is O(N), binary search is O(log(N)) and a hash table lookup is O(1). What if I told you that all of the above is wrong? What if I told you that iterating through a linked list is actually O(N√N) and binary searches as well as hash lookups both are O(√N)?Read More