Posted: January 24th, 2016 | Author: Eugene | Filed under: Soapbox, Tutorials | No Comments »
Wow, 2 years without a post. Time sure flies when you’re having fun! Since I happen to know that a lot of my friends and former students are currently partaking in the great job hunt, I figured I’d write on this, given the large number of interviews I’ve ended up conducting over the years.
The most important thing to realize in interviews is that time is precious. During this time, the interviewer has to find out as much about you as possible and figure out where you might best serve the company. There is an objective behind every single question asked, no matter how trivial or complex. They do not expect you to be able to answer every question flawlessly, but instead seek a better understanding of your personality, aptitude and experience based on how you tackle the problem. So do not panic if it seems you are drowning in the unknown. Just breathe in and embrace the liquid mayhem.
There are 4 basic qualities that I personally look out for in interviewees. They are not the guidelines dictated by any specific company, but have slowly evolved in my head over time. These are them in order of importance.
It is vitally important that you are able to express your ideas clearly, and understand what is being conveyed to you. If you do not speak the native language of the company well enough to be understood, that is a blocker.
More than that, the way you speak reflects upon the way you think, regardless of any language impediments you might have. A good interviewee would speak clearly, concisely and to the point. A bad one will ramble on, beating around the bush before eventually (or sometimes not at all) getting there. This is not a high school test where if you hit the right keyword, you get the marks because it is in the marking scheme.
Often, I will ask a deliberately vague question to see if the interviewee will clarify the problem parameters, and if not, which direction they go in and what assumptions they make.
One of the main tasks of the interviewer is to figure out what level you are at, how valuable you would be as an employee (i.e. how much they should pay you), and whether you would be suitable for a lead role. From simply talking with many people, I’ve come to recognize that there are certain basic qualities that allow easy categorization regardless of discipline (i.e. this works for artists, producers, etc. as well). As much as people try to over-represent themselves during interviews (from either ego or deceit), these are aspects that simply cannot be falsified. Job experience and academic achievements do not factor into this assessment.
Non-starters are people with basically zero aptitude. They fail due-diligence questions like “What is a dot product?” or “Describe inheritance in OOP.” I have encountered Masters graduates who could not write a single coherent line of code. Sad day.
Juniors have a good grasp of the concepts and are eventually able to solve problems. They will often fail to consider edge-cases and do not necessarily grasp the implications of the smallest of their decisions, at least until it is pointed out to them. However, good juniors are humble, eager to learn and are reasonably good at solving puzzles.
Mid-level engineers are insufferable because they know just enough to be dangerous. Their hallmark is over-thinking and over-engineering. They will often have elaborate and complicated designs to circumvent pitfalls they encountered in the past while opening up a dozen more. They look for “tricks” in the interview questions and try to pre-empt them, often fouling up the basic answer in the process. They almost always think they are much better than they actually are, not necessarily through hubris, but because they haven’t yet developed an appreciation of the breadth of things they are unaware they don’t know. They write know-it-all articles, much like this one.
Seniors are hard to find. They have developed a consistent internal framework through which they can solve the majority of problems they have not encountered before. They have a holistic sense of the game development process and are empathetic to how their choices affect the project, and how solutions and/or compromises can come from other disciplines. Their solutions may seem magical or out-of-the-box to others when in fact, they simply have a bigger and better organized box. When they encounter problems they have no immediate answer for, they get excited because it is a learning opportunity and a chance to expand their box even more.
Most companies are looking to fill a gap. We need somebody to do X and X and X. The larger the company, the more specialized this would be. This is because the added depth adds a lot more value to the company than just another generic programmer would. If interviewing a graphics programmer, I would expect him/her to write better shaders than I can, and maybe I can pick up a thing or two from them during the interview if I am lucky.
Smaller companies prefer general programmers because they can tackle many different tasks and generally solve the problem with a satisfactory result. They are the most cost-efficient way to get the game out of the door. This is what results in the difference in quality (and budget) between indie games and those coming out of the mega-corps.
Sometimes during the course of the interview, it will become apparent that your current skills do not match the niche they are trying to fill. At this point, it is a good idea to point this out and declare yourself unsuitable for this particular role. It would spare the interviewer the awkwardness of figuring out how to break it to you gently, and displays a maturity and clarity that will bear you in good stead when a position that does fit you opens up.
Cynics define passion as a direct measure of how little a company can get away with paying you to do the most amount of work. This is not incorrect. In the end, it all comes down to business. In a creative industry like game development, a heavily-self-motivated employee will be a thousand times more productive than somebody who’s just doing a job. Also, they would be less likely to leave at the first sign of green pastures, particularly in the middle of a project.
However, passion is much more than that. Why do you want that particular job in that particular company as opposed to anywhere else? What should the company do to keep you happy? What can the company do to make you deliriously ecstatic? If your answer is “More Money!”, I would recommend a job in the financial sector. Game development is not for you. Otherwise, being clear and truthful about what the company wants out of you, and what you want out of the company will make the relationship infinitely simpler and easier to manage.
The interview process is a two-way street. Both parties are trying to find out if there is a way for them to reasonably work together. Over-representing yourself is a common mistake as it murkifies the communication. (Besides, we know when you’re naughty!) I believe that for interviews at least, being honest and upfront (within the constraints of any NDAs) is the best policy. You don’t just want a job. You want a job that will make you happy, and will make your future employer happy to have you.
Here are some common interview questions. Can you tell which qualities they are trying to measure? (hint: it’s often more than one)
- Why do you want to join our company?
- Describe your proudest achievement to date.
- What’s the biggest challenge you’ve encountered so far in your career? How did you overcome it?
- What games do you play? What do you like about them?
- What is your opinion of overtime work?
- Please write some code that does this ridiculously simple task. What trade-offs did you make? How can you improve it?
- What’s the difference between a vertex shader and a pixel shader?
- You need to transport a dog, a cat and a mouse across a river. You can only carry one animal with you in your kayak at a time. You can’t leave the dog alone with the cat. You can’t leave the cat alone with the mouse. If you put the cat in the kayak more than twice, it will scratch your eyes out. What’s the minimum number of trips you need to make to get everybody over to the other side?
- How would you deal with an unreasonable supervisor making stupid (in your opinion) decisions?
- Have you any experience with Shaders? How about multithreading? Pathfinding? Networking? Physics? UI? Anything? Anything at all?
- On a scale of 0 to 9, rate your C++
Posted: March 26th, 2014 | Author: Eugene | Filed under: Tutorials | 1 Comment »
How do you explain what depth-write and depth-test means to a non-technical artist or designer? The obvious answer is you search Google for a well-written introduction to the concept of depth buffers, and point them in direction. Somehow, my Google-fu failed this time, and I could not find an article without scary OpenGL code or mathematical formulae. So, here I am, writing this out. My public service for the year.
The Painter’s Algorithm
So let’s go back to the beginning when painting was a simple matter of putting brush to canvas. If a painter of yore were to draw the Success Kid meme, how would he go about doing it? It would probably go something like this:
You start with a blank canvas, draw in the background, followed by the kid, and finally the text. Notice that you are layering things on top of another from the back-most to the front-most. This method is called the Painter’s Algorithm. So why can’t computers do this too? Well, the answer is, they can! The only problem is that it is slow, because we are drawing a lot of pixels that won’t eventually make it to the screen. Consider the part of the background behind the kid. We can’t see it, but yet we are drawing it, only to overwrite it again later.
So how expensive is it really to draw a pixel? Consider the obviously high-poly, normal-mapped, specular and fresnel lit Success Kid model. There are two factors under your control that directly affects how long it takes to render it on screen. The first is your vertex cost, which is roughly the complexity of your vertex shader multiplied by the number of tris, verts or polys that make up your model. The second is the pixel cost, which is the complexity of your pixel shader multiplied by the number pixels the polygons are occupying on screen (including all the alphaed-out bits).
For better or for worse, the shiny stuff that all artists love (and therefore cost the most), usually reside in the pixel shader. Per-pixel lighting, normal maps, environment maps… they all severely skyrocket the price you pay for each pixel. That’s why for shiny stuff, we want to minimize the number of pixels that are drawn as much as possible, especially those that don’t need to be considered.
It didn’t take long for somebody to come up with the bright idea of drawing things in reverse order. If we draw the kid before the background, we wouldn’t have to draw the part of the background that is hidden (or if you want to sound real smart, occluded). So the draw sequence would go something like this:
Front to Back
So now before we draw each pixel, we just need to check and see if that pixel has already been drawn. If it is already there, we skip the pixel at proceed to the next one. As Farengar Secret-Fire would say, “Simplicity itself!”.
This is where the depth-buffer comes in. The depth buffer serves as a record of what pixel is drawn and what is not. So as we draw things on screen (i.e. the color buffer), we record down in the depth buffer that we have drawn to this pixel. This is called depth-write. The next time we want to draw to the same pixel, we check the depth buffer to see if the pixel has already been drawn to, and if so, don’t do it. This is called depth-test.
I know the question that’s burning a hole through your brain. “If it is simply a record of what pixel is drawn, why do we call it a depth buffer?”
What, it wasn’t? Well now it is, isn’t it? Before we answer that, let’s take a look at a problem we conveniently glossed over.
The Alpha Problem
Let’s revisit that approach with the full image:
Oops, do you see what happened there? Our “Success!” caption was drawn on a single quad, with all the transparent bits alphaed out. Since it is front-most, we draw that first. When we draw the kid, it sees that those pixels are already drawn to, albeit with zero alpha, and doesn’t draw to it, so we never get to see the pixels that are behind the space between the letters.
There are a number of ways to solve this problem. We could model each of the letters individually, so that the texture is fully opaque. The problem with that is that your vertex count increases a lot, especially if you want smooth curves. Also, it doesn’t handle the case of translucent pixels (i.e. with partial alphas), that would still need information on what’s behind it. This might still work for some cases where the vertex overhead is not that big. If you can get away with this, do it!
Another way is alpha rejection. Whenever the pixel shader sees that what is about to be drawn has an alpha value below a certain threshold, don’t draw it! This solves the cost of having many vertices, but still doesn’t solve the translucency problem. This also ruins the day of some graphics chips (most notably, the PowerVR chip found in iPhones and some Android devices) which optimize around the idea of not having pixels being rejected by the shader.
The ultimate solution is acknowledging that we don’t really have a clue of what to do, and go back to the Painter’s Algorithim. However, this time, we can be smarter about it. Divide all our objects into two groups—those with alpha, and those that are fully opaque.
First, we draw all the opaque geometry sorted front to back, making use of the depth buffer. However, instead of just storing a plain “Have we written to this pixel”, we store the depth value. (i.e. how far is this pixel away from the camera) After that, we draw all the alpha geometry from back to front, checking the depth buffer against the depth value of the pixel we are about to draw. If we find that we are drawing behind something that’s already drawn, don’t draw it because we know that it will be occluded by an opaque object. Otherwise, we would draw on top of it, blending with any pixel information that might already be present. Since we are drawing from back to front, there is no need to waste time writing to the depth buffer.
Opaque followed by Alpha
This leads us to the general rule:
- For Opaque Geometry: enable depth-write, enable depth-test
- For Alpha Geometry: disable depth-write, enable depth-test
You should also be aware of how to let the engine or game know what is opaque and what is not. In most editors, you can simply disable blending. This is really important. An opaque object with blending on will still look right, but will incur the cost of a transparent object.
As your astute mind would have observed, using a lot of overlapping alpha leads to copious amounts of overdraw (redrawing the same pixel). The more screen space this takes up, the worse it gets. Thusly, we finally arrive at the moral of the story.
Alpha is evil! Shun it like the cancer that it is!
Common Artifact 1: Intersecting Alpha Geometry
If you have two pieces of alpha geometry that intersect or interlock each other, which one do you render first? Whichever one you pick, the one that is rendered first would not have the pixel information of the other, so blending will never be accurate. Stop tormenting your poor programmer… there is nothing he can do! This is further proof that alpha is evil.
Also, if you do tricks that offset the origin of a model, which messes up the sort order, you might get the same artifact we saw with the “Success!” text above. Your programmer can solve this problem by selectively sorting it, but usually at a cost. Tricks are evil too!
Common Artifact 2: Z-fighting
Occasionally, when two pieces of geometry are very close together, you may either see them flicker or observe moving stripes on them. This is because you have hit the limits of the depth buffer. The depth buffer is not continuous. You can envision it as dividing the space between the near plane and far plane of the camera into slices. If the pixels you want to render are on the same slice, the poor GPU is going to get confused which is the one true pixel. There are a number of solutions
- A 16-bit depth buffer would have 65,536 slices. A 24-bit buffer would have 16,777,216 slices. A 32-bit buffer would have 4,294,967,296 slices. So the obvious solution is to increase the size of the depth buffer. However, depending on the hardware, this is not always possible.
- You could move the objects further apart, which is the most common sense thing to do. However, visually, it might look a little off.
- Another trick is to adjust the camera so that the far-plane is closer to the nearplane . This will squish the slices closer together, making them thinner, and therefore decrease the chance of z-fighting.
- You can move the offending objects closer to the camera.
That last one needs some explaining. If you have a purely orthographic camera (i.e. there is no perspective. Far away objects don’t appear smaller than closer objects), all slices are equally spaced from the near plane to the far plane. However, for perspective cameras, these slices are not born equal. Instead, they are bunched up close the near plane and get exponentially further apart as you approach the far plane. There are tricks that your programmer can do in the shader to reduce this effect, but as noted in the previous section—tricks are evil!
Posted: September 22nd, 2013 | Author: Eugene | Filed under: Hermit, Tutorials | 1 Comment »
Typically, resource systems are created as an afterthought. When the need comes to load or save some piece of data, a bunch of file io code is written and left to languish until it gets so convoluted that some unfortunate soul is tasked to go clean it up. This is sad because as one of the main backbones of the engine, any design misdemeanours will have a tremendous ripple effect throughout the whole code base. After having put considerable thought into it, I present the design of the resource management system for the newly christened Hermit Engine. (Hermit, because it is designed by lone wolf coders for lone wolf coders ;))
Anatomy of a Resource System
Before we dive in, let’s take a look at what the resource system needs to achieve. Much more goes into it than simply loading and saving files. The resource system will be responsible for loading up all assets that are needed by other systems (shaders, textures, scripts, audio, geometry, etc.). This could come from a variety of sources, be it a simple folder structure, compressed archives, a database, a network stream or any other data source. It needs to ensure that all resources are loaded only once, and are reused when possible so as to keep the memory footprint as small as possible. Ideally, it would be able to load resources at the beginning of levels so that no file io or allocations would happen during the main gameplay phase as these may cause stutters in frame rate. It needs to identify the different types of resources so that they can be funnelled off to the appropriate subsystems for usage. Also, when requested resources are not found, it should be able to substitute in default resources instead of simply crashing.
For Hermit Engine’s resource system, we will lean on 3 main pillars: The basic resource type, the resource pack, and the resource pack loader.
The Achilles heel for most resource systems are the humans that use them. Because of humans, we need human readable resource names. We need unwieldy folder structures so that the fleshy brained can find their stuff. As a result, we end up with elaborate string libraries, hash tables, directory traversal, and other icky constructs to deal with their archaic naming conventions. Remember the ripple effect we mentioned earlier? To all this, Hermit says, “Screw humans!”
The Hermit’s resource comprises of 3 pieces of data. The first is the resource identifier. Naturally, this won’t be a string. Instead, it will be a 32 or 64 bit integer (depending on how many resources you have). The highest few bits of will represent the resource type. The next few will indicate which resource pack it came from. This will eliminate the need to store some sort of global identifier counter. The few after that will be a subtype that each system can define. For example, the shader system might want to differentiate between vertex, pixel and geometry shaders. After that, you simply have a running number. If this number happens to be zero, that would be your default resource. Default resources will always be available even in the absence of data because they are procedurally generated (remember the whole point of this engine?).
This will let you easily enumerate all the resource types with a simple enum. Need default geometry? Just request for RESOURCETYPE_GEOMETRY. Need to know what resource type a given resource type is? Just & it with a high-bit mask. Want to sort resources by resource type for more efficient loading? Just use a simple int-compare on the resource id. Everything becomes simpler once the foundation is laid.
The second piece of data that the resource would need is the source information needed to generate the resource. For shaders, this would be the uncompiled script. For geometry, this would be spline and fractal fields. The last piece of the puzzle would naturally be the compiled data. A shader id in the case of shaders or a VBO id in the case of geometry. The source data is what gets saved to disk. During the game’s execution, the source data is read in when a resource is loaded, dished off to whatever system in order to get the compiled data, and then jettisoned since it is no longer useful. If it was still useful for any reason, it would be part of the compiled data. In the case of an editor (you were planning on having one, right?), the source information is kept in memory so that it may be displayed, edited and used to regenerate the compiled data.
“But I’m a human, how will I ever find my stuff amongst all this binary gibberish?!”
The engine won’t sully itself with this since coddling humans is not its problem. However, the editor will maintain a two-way human_name<–>resourceid map so that when information is presented to the human, they get to see their precious strings. After all, it’s the editor’s job is to act as an interface between human and machine.
Resource packs are what they sound like. They are responsible for grouping related assets together and treating them as a batch as far as loading and unloading goes. They provide the structure which forces the human to think closely about what’s in memory at any one time. For a simple level-based game, you would typically have a pack for all the common elements, and a pack for each level. As you move from level to level, you unload old packs and load new ones. This guarantees that you won’t be doing any file io or memory allocations (with regard to resource handling anyway) that may cause stutters during the main gameplay. Furthermore, it accomplishes this without reference counting or any other clunky mechanism.
“But wait! I’m making a super huge MMO WoW-killer that needs to stream in assets on the fly. I can’t do things level-based!”
First off, if you are a lone-wolf programmer making a “super huge MMO”, it would be my duty to inform you that you are bat-shit crazy and should turn back while you still can. That said, if you still have your mind set on it, all you need are smaller packs. Your packs would contain all resources related to that particular entity: it’s geometry, script, audio, etc. This would handle the problem of making sure all assets are present before trying to display the object. Shared resources can be stored in zone-wide or global packs.
Regardless of how it’s done, the smart designer will keep most if not all dependencies within a pack so that they get loaded/unloaded together. Once everything is viewed modularly in terms of packs, inter-dependency management should become pretty easy. Furthermore, since we are lone-wolf programmers, we only need the modicum of support for stupid design—assert(IsDesignerBeingStupid()).
This is the part that does the file io. Its interface would only have three main methods: load a pack, unload a pack, and save a pack. You can have different loaders to cater to different needs. Here are a few examples:
A lot of people seem to like keeping all their assets in version control for some reason or other. You can have the loader write out to a directory structure which can then be checked in. If you really want to, you can also make use of the editor’s mapping to write them out into human filenames rather than just plain ids, complete with convoluted directory structure.
One of the better places to store data for editing would be in a database. This could be as simplistic SQLite or as elaborate as Oracle. This is handy for synchronization of assets between multiple machines, DLC management, statistics gathering, and those shady mass-edit operations that no self-respecting developer would ever admit to doing. The danger here is that a corrupt database could ruin your day.
For runtime, most resource packs would end up in compressed archives. The pack nature, makes this extremely easy. Instead of having to compress each resource individually, you simply compress the whole pack. The header would simply comprise of resourceid<–>offset_location pairs. When loading, you load the whole pack, decompress the whole thing, distribute offset pointers to each of the resource consumers to generate compiled data. After that, just free all the source data at once.
If you really want to, you could even have loader that reads off a network stream for dynamic runtime sharing. However, being the HERMIT engine, we network and share with nobody.
Posted: July 14th, 2013 | Author: Eugene | Filed under: Hermit, Projects, Tutorials | 1 Comment »
Once upon a time, there was a project called Darwena. This was to be a game engine built from the ground up with the aim of reducing our reliance on that other group of people that are kinda crucial to game development. (the artists!) That project started up fairly quickly, with cross-platform input and rendering implemented, even a little text. However, that project died just as quickly when I joined the ranks of Gameloft. Many factors contributed to that. There was the fear that as a generic employee in a generic evil empire, my work would simply get assimilated into the host. There was the lack of time and energy due to the crazy scheduling of a freshly started-up studio (albeit under the umbrella of said evil empire). Most of all, I start learning a whole lot and discovered (i.e. had my nose pushed into, gently) a lot of concepts that made my previous work look like the inane doodles of a three-year-old. (no offense to three-year-olds, you rock!)
Well, most of that has changed now. The wild schedule has been tamed. The powers that be have given their blessing to my pursuit of non-commercial project work. Most of all, I’ve learned enough that I just need to write something to congeal all those disparate concepts into a contiguous body of knowledge. Also, I now have a conducive work area in my apartment, all ready to get those creative juices flowing!
- It will be cross-platform across Windows, OSX and Linux, though most work will be done in Linux. (because we can!)
- It will be multi-threaded, and data-oriented, and component based. (I was told that component models tend to not work well. Time to test that!)
- It will emphasize procedural generation. However, we’re not targeting the sort of procedural generation that we find in the demoscene which creates a lot of pretty stuff with very small code and assets. Instead, we will be generating assets non-realtime (unless things go exceedingly well), mutating and splicing them with genetic algorithms using human input as the fitness function, in order to produce not-so-abstract-looking visual and audio assets. This is not a new concept, but it sounds like fun and worth exploring.
- There will be an editor for creating content, possibly including game levels.
- Text input and editing will be highly emphasized as the main means of control. The target users are programmers, so there’s no fancy drag-and-drop-connect-the-dots nonsense going on. Command prompt ftw!
- There will be a scripting language for fast prototyping, most likely AngelScript because the C++-like syntax might be easier to copy/paste into actual finalized code. Also, the exposed debugging interface would allow us to do breakpoints, watches, etc. within the scripts through our custom interface.
- The first asset generation milestone would be creating X different assets with different mutations for the human to select and filter through.
- The second asset generation milestone would allow splicing of two or more assets into one.
- The third asset generation milestone would be finer-grained gene manipulation.
Despite all the fancy stuff, a game engine is still a game engine and will need the same basic things. Our design will emphasize mulththreading while trying to steer away from excessive mutex use or double-buffering of data. Instead, we apply the data-oriented paradigm and look to transform data from one form to another with each module. On a very high level, it may look something like this:
The Simulation module is basically a huge collection of cascaded step functions. This would can be thought of as a physics process. For example, you use acceleration to step velocity. You then use velocity to step position. However, this could apply to HSV color, audio frequency, emotional state, etc. This is very likely to eventually comprise of many submodules to handle different types of algorithmic relationships. I’ve still to sort this out in my head.
The Steering module takes the output from the simulation in order to generate control inputs for the next simulation step. It can also take additional input from its internal stored state or from external sources like human or network interfaces.
The Rendering module simply takes the output from the simulation and splats it on screen, speakers or whatever other output device so that we humans can perceive what’s going on in there. In a sense, this is just a slightly twisted MVC model.
The whole pipeline will run as if it were in a single thread but each of the modules that execute will be threaded. This will allow us to scale dynamically as more processors become available, and will also let us collapse back down into a single-threaded system for easy debugging. Each of the modules or submodules will load balance by simply dividing the number of tasks by the number of processors. We can do this as long as all the submodules are homogeneous in the sense that each task will take about the same amount of time to execute. The only exception to this is rendering which generally likes to run from the same thread, and is thus run in parallel with steering since they operate off the same immutable data. This may cause bubbles in the pipeline, but that’s another worry for another day.
Where are we now?
Currently, we have rendering up on all three platforms, as well as a modicum of input processing. Project/makefiles are generated through CMake. This includes the main engine library project, as well as a project for the editor that runs on the engine.
The next stop is the resource system. Stay tuned!
Posted: May 12th, 2013 | Author: Eugene | Filed under: Soapbox, Tutorials | 2 Comments »
Until a year or so ago, I was a C++ purist. This was fair, because as a game programmer, generally you would want your code in C++ 99% of the time. The object-oriented style it promotes helps a lot in scalability and code management. Any super-time-critical code would mostly be handled by the engine anyway. Also, as a superset of C, there’s technically no reason why it can’t do everything that C can do. However, coming across game engine code written in C, most notably in HGE, Orx and RK, was an eye opener. There is a poetic simplicity and succinctness to the code. Just reading the code alone makes you instinctively feel that it should be faster, even if just by a smidgen. Much of this past year was spent ping-ponging between the two concepts, trying to figure out which one I like better.
Why C++ instead of C
Namespaces are wonderful to have. Ultimately all you want to do is prevent naming collisions. C gets around this by generally having absurdly long function names like BlahBlahEngine_GetIrritatingObject() which ultimately makes the code harder to read. In C++ GetIrritatingObject() is simple and to the point.
Operator overrides are also very nice when used sensibly. Case in point: which is easier to read?
Vector a, b, c, d;
Vector_Set(a, 1, 2, 3);
Vector_Set(b, 3, 4, 5);
Vector_Set(c, Vector_Add(a, b));
Vector_Set(d, Vector_Mul(c, 3));
// C++ Code
Vector a(1, 2, 3);
Vector b(3, 4, 5);
Vector d = (a + b) * 3;
This readability can also be a detriment if badly used, because the programmer is not made aware of the cost of each operation. This, however, can be circumvented by simply having more alert programmers! 😀
Resource acquisition is initialization. This is one of the little tricks used by smart pointer classes to ensure that memory is cleaned up after them. In general, I don’t like smart pointers. Sure, they are a convenient way to manage memory, but abuse of them tends to lead to bad architecture (more on this later). However, I do like to write almost all my classes using the RAII paradigm. While it has the side-benefit of making your code exception-safe, it also encourages what I consider to be good architecture—in that everything is allocated at once (and therefore most likely in the same area of memory), and no strange allocation happens through different code paths.
C generally uses Init and Deinit functions. These are not exception-safe (i use the term liberally), so if your application gets shut down unexpectedly half-way, it will most likely leak memory. Some OS’s might sandbox you, but not all do.
Love or hate them, they are still useful for all sorts of things, most notably container classes. Their shortcomings are well documented—hard to debug, inconsistency between compiler implementations, etc. I equate them to C macros, but with more use cases and potential problems. Overall, they are a net gain, but I would still shy away from STL/Boost unless I know their exact implementation. I tend to use these more for my own custom classes, but
the moment ugly template magic starts happening, I take pretty much any other alternative I can.
Why C instead of C++
Object vs Data Orientation
We all know object oriented code. After all, it is what was promoted when we were in school, even though at the time, we all secretly wanted to write everything in one big function and be done with it. The structure it enforces produces very scalable and flexible code. It also had the benefit of localizing all data for an object in the same spot of memory, which was and still generally is a good thing.
Data oriented code is the new (relatively speaking) paradigm of envisioning code modules as data manipulation. You take in an input and produce an output. By cleverly organizing your data in a somewhat unobject-like way, you can have the same operation acting on mass amounts of data that happen to be all located sequentially next to each other. As a wise man once summarized, you organize your data as a struct of arrays, rather than an array of structs. The benefit of this is that your data is more cache-optimized, and also lends itself more easily to parallel processing.
Now, it should be noted that both C and C++ are capable of implementing both paradigms, even at the same time (they are not mutually exclusive). However, by its nature, C++ nudges you to think in a more object-oriented way. C doesn’t nudge you at all, and has absolutely no qualms to letting you chop off your own foot if you so desire. It is, however, somewhat easier to head down the data-oriented route without the uneasy feeling that you are doing something naughty. I found the best way to not feel guilty is simply to stop feeling guilty.
The Singleton Problem
This is one of my biggest peeves with object-oriented languages. Let’s say you want to write an audio module, with functions like PlaySound(soundid) that everybody and their grandmother wants to call at some point. OO logic dictates that there should be some kind of SoundManager class, and since there should be only one of them, the Singleton pattern is followed. Thus every time you want to play a sound, you would do something like SoundManager::GetSingletonPtr()->PlaySound(soundid). Depending on your implementation, GetSingletonPtr could contain a branch to check if the singleton exists. Also, managing when your singleton object gets allocated, intiated, etc. is a pain. Of course, there are at least two dozen singleton variants that get around this in various ways. But that’s a lot of reading…
C, on the other hand, is made for modules. By embracing the “evilness” of a globally defined function, one can simply call SoundManager_PlaySound(soundid). Firstly, it’s as simple as just calling a function. In fact, it is just calling a function! Secondly, your module would have already been inited and deinited at startup and shutdown giving you unequivocal control over the lifespan of the SoundManager.
I get around this by embracing the “evilness” of global objects. All these objects’ lifetimes are managed by a single RAII manager class, but pointers to them are available in the global scope. SOUNDMANAGER->PlaySound(soundid) is not bad, though still not as “clean” as the C way.
Convolution in the Name of Safety
C/C++ was generally regarded as one step up from assembly. When you want finer-grain control over what happens where, without explicitly dictating each opcode, they would be your languages of choice. Lately, C++ has been moving away from that shaky ground. The additional functionality like smart pointers, dynamic casts, templatized algorithms and libraries, are all there in essence to prevent you from screwing yourself over. The cost to that is that you are removed further from implementation details. When I malloc() something, I get a chunk of memory, When I new() something, I get an object, with it’s constructor called, and whatever happens in there. This is not a bad thing, and probably improves the quality of life for C++ programmers in general. The thing is, if you are going in this direction, why not use a language like Java or C# which was designed for this role in the first place?
Instead of writing code to prevent programmers from doing stupid things, why not have smart programmers that won’t do stupid things in the first place? Game programmers, especially engine programmers, are control freaks when it comes to what their code does. Sometimes, we do want to shoot our own foot off (because it’s amusing?), so let us and stop asking questions!
I get around this by simply not using the C++ features I don’t like. Yes, I use new and delete, since I know what they do (as long as they are my own classes). I use sprintf instead of stringstreams which are just clunky. I use arrays instead of vectors. I use the C string manipulation functions or simply roll my own instead of std::string. I use C casts instead because it is briefer, and architect so I won’t be in a position to cast the wrong pointer. That last one is particular poignant. With all the convenience tools taken out, you are forced to look at your architecture, design it sensibly, and generally be more aware of the different interactions. (The same can be said for avoiding VisualAssist, but that’s a rant for another day!)
Posted: February 6th, 2013 | Author: Eugene | Filed under: Projects | 3 Comments »
Hi everyone! It’s been a long time since I posted. In fact, it’s almost been ever since I joined Gameloft. The corporate hush-hushness has been keeping my lips sealed. However, now that several games have already hit the markets (for some time), now would be a good time to list them out and add them to my online portfolio. If you are looking for amazing revelations and insights, sorry. This is more of a “Look what I did!” post.
First, the ones that didn’t quite make it, and hence I can’t say much about. The first is an the Android port for the very first game published by the Auckland studio. Unfortunately, the port was later abandoned for reasons we shall not say. I also worked on an experimental project which, for blogging purposes, we shall call “Mystery Island”. Unfortunately, Mystery Island did not make it past the prototype stage, but it was very pretty. (We were definitely carried by the amazing art team for that one!) Ah well, rough start!
In the meantime, I did contribute to two games that did make it to the market. Playful Minds: Math, and Men In Black 3. While I wasn’t a main developer for either of these, I contributed via bug-fixing in the former and performance optimization in the latter. Apparently, that was good enough to get my name in the credits, so yay me! Playful Minds is an educational game that was inherited by our studio. A lot of sweat and tears went into making it as it was one of our first projects, and nobody was quite sure which way was up yet. MiB3, on the other hand, was developed in another studiol, and they were under tremendous pressure to release in time for the movie premier.
Now for three games that I did play an active role in: Wonder Zoo, My Little Pony and Littlest Pet Shop. Note that they are all freemium games. Yes, the exact kind that you can get off the AppStore for free, but extract money from you later by exploiting your psychology. It’s a diabolical scheme, but a good coder puts himself beyond petty things like good and evil. It’s all just 1’s and 0’s in the end, and the weak-willed will always be susceptible to mind tricks anyway. They all run on both iOS and Android. We do not discriminate! (except against Blackberry, Palm and Windows… oops!)
All of these games were developed on a framework that I helped architect and wrap around Daniel Stephen’s RKEngine. (I can say that because it’s in the credits!) Note that when I say architect, what I really mean is that a few mates and I wrote some of the initial base classes and processes, but because our engine team was tiny in its infancy, everybody (and I mean EVERYBODY) chipped in bits and pieces. A true Frankenstein framework, but it LIVES!
Now would be a good time to give a shout-out to Remi Akilapa, who passed away unexpectedly during the very early formative years of this framework. He was a brilliant coder and engineer, who had a tremendous stabilizing influence before we found our footing. We kept each other sane through countless meetings with designers, artists and producers, sharing the mantle of technical leadership that neither of us really wanted to bear. Thankfully, I don’t have as many meetings to attend now that the studio has had time to mature. I would much rather be writing code. RIP my friend!
Finally, a note on a game that was not made by Gameloft. MechWarrior: Tactical Command was released by Personae Studios in September 2012. I worked with them part-time for a year, departing roughly 2 years before the release date. By that time, we had established their base engine tech, as well as a couple of (very) rough prototype levels that the team put together during one amazing week of glory. I don’t know how much of our work made it to publication, but I’m glad it did finally hit the store. The sad news is that it is iPad-only, so I won’t get to show it off.
Posted: July 23rd, 2011 | Author: Eugene | Filed under: Tutorials | No Comments »
As indie or casual game developers, we seldom get the chance to play with shaders. The reason why is that there simply is no need to get ourselves involved in all that “stuff”. The engines that we work with come with most of the stock shaders that we need, so all that is required is a basic understanding of what they are and what they do. Kind of like suntan lotion, you don’t question too deeply how it works. You just slap it on.
Recently however, I have had the occasion to dabble in shaders and found that it is really not all that complicated. So here’s a little overview to get you started.
Some time ago, shaders were written purely in assembly, much like how normal programs were written a longer time ago. The next natural step in evolution was of course to spawn a set of high level languages to deal with the complexity. HLSL was coined by the folks at Microsoft. It works in tandem with DirectX, meaning it’ll run cross-platform as long as by cross-platform, you mean Windows and Xbox. GLSL was spawned by the hippie open-source community and works as a direct extension of OpenGL, so it will run everywhere else. The folks at NVidia came up with CG which doesn’t really run anywhere but instead compiles into both HLSL and GLSL, presumably saving time writing shaders in both languages.
Structurally, they are all the same. It is only a matter of syntax and code rearrangement, if you ignore some of the more esoteric features of each language. All of them give you the power to manipulate matrices and vectors as easily as you would mere integers in traditional programming. They are also designed to be (potentially at least) massively parallel so more things can be done faster, which is generally a good thing. The price, however, is limitations in what you can actually do within your shader.
The programmable pipeline as they like to call it, differentiates itself from the more traditional fixed pipeline in the sense that it is, well, programmable. This gives the programmer (or artist, if the dirth of shader generation tools keep growing) more power over the rendering process.
The old way of doing things was that you’d fill up vertex buffers with vertices, index bufferes with indices, strategically position a few lights and define a few global parameters. After you have everything configured sweetly, hey presto, there’s your pretty picture! The main errors students commit using this traditional workflow are trivial things like… do you have a light in the scene? Is your camera pointed the right way? Is the object so small that it is occupying less than one pixel on screen? Ahh… life was simple back then!
Nowadays, you start of with a set of vertices. These could come directly from meshes or they could be generated from geometry shaders (I don’t know much about geometry shaders so I’m not going to say much about them). It doesn’t matter. Each and every vertex gets run through your vertex shader program. This happens four, eight or however many channels your graphics card has, at a time. As a result, you can’t get information on the other vertices (unless you are especially clever and sneaky about it), but you can pretty much do whatever you want with the vertex you have. Change its position, its color, its normal or any other of its attributes. Totally up to you. Of course, with great power comes great responsibility, and with great responsibility comes greater potential to f*** things up.
Once all the vertex processing is done, your vertices get rasterized. Usually, by that, we mean that they get transformed to 2D screen coordinates, but that isn’t exactly true. It is the job of your vertex shader to transform the vertices into 2D coordinates (it’s just a matrix multiplication, not hard). What the rasterizer does is it goes through the pixels between your vertices and interpolates the values. So if you have one vertex that is red and another that is white, all the pixels in between will be varying shades of pink. This doesn’t just happen for your colors, but also for normals and whatever other attributes you may have chosen to endow your vertices with.
Each of these pixels is then fed into your pixel (if you are from Microsoft) or fragment (if you are a hippie) shader for further processing. There, you can do a whole bunch of other complex or simple operations, simply to figure out what color you want to paint that particular pixel. As per your vertex shader, you only have access to that one pixel throughout your shader, and the pixels themselves get pushed through n channels at a time, depending on how much your vendor crippled your graphics card via firmware.
Finally we get to the code part of things. I’m going to compare CG and GLSL, mainly because CG and HLSL code look pretty similar, and CG has less letters.
There are four general data types to be found in a shader language.
- There’s the basic floating point number, which all three languages have aptly named “float”.
- There’s the vector of varying sizes, called float2, float3 and float4 in CG, or vec2, vec3 and vec4 in GLSL
- There’s the matrix of varying sizes, called float2x2, float3x3, float4x4 in CG and mat2, mat3 and mat4 in GLSL
- There are textures of varying dimensions, called texture2D, texture3D and texture4D in CG and sampler2D, sampler3D and sampler4D in GLSL (don’t let 4D textures blow your mind!) These are essentially the equivalent of lookup tables.
Of course, there are a lot more actual data types than these, most having to do with fixed-point math or irregularly shaped matrices. You also have bools and stuff, but you can figure those out on your own.
Types of Variables
As you may or may not have gathered from the section on pipelines, much of the idea behind shaders is about data flow and how it trickles down into the pixels. As a result, we have four types of data.
Uniform variables are stuff that you just sorta shove into the shader. How they get in is up to you. Some have them as part of the exporter from Max or Maya. Some have them built into the level editor. As long as you feed your shader before you run it, all will be well. Here’s your world matrix, a handful of numbers that should mean something and a few vectors for good measure. glhf! CG embraces the evil and defines these as simply global variables within the shader code. GLSL is more circumspect and demands that you use the keyword “uniform” to denote them. GLSL also has a whole bunch of predefined uniform variables just to keep everybody on the same page.
uniform float time;
uniform float amplitude;
uniform float frequency;
uniform float ambient;
uniform vec4 lightdir;
uniform sampler2D tex0;
Uniform variables aren’t your only form of inputs. There are also vertex attributes. These are attributes that are defined as part of your vertex data structure. They can include mundane things like color, normals and uv coordinates, as well as customized data that only has significance to your skillfully crafted shader. How do you generate these vertex attributes? They can either be pre-calculated, or more often than not, are “painted” in by the 3D artist.
float4 position : POSITION;
float4 color : COLOR0;
float4 normal : NORMAL;
float2 texcoord: TEXCOORD0;
//attribute vec4 gl_Vertex already defined
//attribute vec4 gl_Color already defined
//attribute vec4 gl_Normal already defined
//attribute vec2 gl_MultiTexCoord0 already defined
In CG, all you do is define a struct and dump whatever vertex information you want into it. This will later be fed into your vertex shader. You can call your attributes whatever you like, but may need to tag them for deciphering purposes. For GLSL, you use the keyword “varying”. Like uniform variables, GLSL has a lot of predefined vertex attributes to cover the usual suspects.
Varying variables are what your vertex shader spits out, and is then fed into your pixel/fragment shader. Remember that by the time they reach the pixel shader, you will more often than not be working on interpolated data. In CG, you define another struct to hold this intermediate information. In GLSL, you use the keyword “varying”. As always, there are a bunch of predefined varying variables.
float4 position : POSITION
float4 color : COLOR0;
float4 normal : NORMAL;
float2 texcoord : TEXCOORD0
//varying vec4 gl_Position already defined
//varying vec4 gl_FrontColor already defined
varying vec4 normal;
//varying vec2 gl_TexCoord0 already defined
Finally, you have the output from your pixel shader. In CG this is, you guessed it, another struct. In GLSL, there’s no keyword. You just use the predefined variables, namely gl_FragColor.
float4 color : COLOR0;
// gl_FragColor already defined
The Shader Functions
After you have defined the data that you are going to be playing with, all that is left is to write the shaders themselves. Each shader is a self-contained function. In GLSL, your vertex and fragment shaders are usually in different files, and the entry point for each one is called “main()”. For CG, however, you can have multiple shaders in the same file and call them whatever you want. Whatever the case, during the actual render process, one program, comprising of exactly one vertex shader and one pixel shader, will be run per mesh per pass.
Here is a vertex shader that bounces the mesh around a bit.
v2p mainV(a2v IN)
OUT.normal = IN.normal;
OUT.color = IN.color;
OUT.position = IN.position + amplitude * sin(time*frequency);
OUT.texcoord = IN.texcoord;
normal = gl_Normal;
gl_FrontColor = gl_Color;
vec4 newpos = gl_Vertex + amplitude * sin(time * frequency);
gl_Position = gl_ModelViewProjectionMatrix * newpos;
gl_TexCoord0 = gl_MultiTexCoord0;
And here’s a pixel shader that computes lighting and figures out what color to render based on the supplied texture, vertex color, directional light and ambient lighting. Note that it would have been more efficient to calculate the texture color as well as lighting in the vertex shader rather than here, so that it is calculated per vertex rather than per pixel. Food for thought… think of all the neat hacks you can do! Also think of all the side-effects!
p2f mainF(v2p IN)
float NdotL = dot(IN.normal, lightdir);
OUT.color = IN.color * tex2D(tex0, IN.texcoord) * NdotL + ambient;
float NdotL = dot(normal, lightdir);
gl_FragColor = gl_FrontColor * texture2D(tex0, gl_TexCoord0) * NdotL + ambient;
Posted: June 18th, 2011 | Author: Eugene | Filed under: Soapbox | 2 Comments »
So e-Goh, the carefree freelance game developer is no more, having crossed over to the dark side of corporate game development with Gameloft, Auckland. Why would I want to make such a move? First, adventure (i.e. get into trouble). Second, to get out of Singapore. Lastly and mostly, it sounded like fun!
How does one get a job with a large game development studio that is located overseas? Quite simply, you apply. I sent out my resume to anybody with an email address. Most useful were the contacts I gained through LinkedIn and Facebook. Pretty much none of them replied. Big studio, small studio, it didn’t matter, and it was expected. That is the way the world is, you can’t just send out your resume and hope for the best. Instead, you have to relocate first, get to know the companies there, and then apply!
Well, apparently Gameloft didn’t get the memo. They replied! They sent me a test to do, which I apparently aced (of course), and then we had a quick interview over the telephone. Just like that, “Wham! Bam! Thank you Ma’am!”, I was in!
Just getting the job wasn’t enough. There’s still the process of actually getting into New Zealand. In order to work in New Zealand, you need a work visa, and they are pretty strict about it. Depending on the length of your stay, you may be required to go for a full medical checkup, get the CID to issue a police report to vouch for the goodness of your soul, and who knows what else? Fortunately, the length of my initial contract was only one year, so it wasn’t too much of a hassle.
On the employer’s side, they had to prove that they actively tried to look for talent in New Zealand and couldn’t find it. Luckily for me, they had already been searching since January last year and we had plenty of documentary proof. They also had to furnish documents like the offer letter, employment contract, etc. for the perusal of the immigration office (which is located in Ngee Ann City, if you’re curious).
After about 10 days, approval was obtained, and all that was left to do is procure tickets, hop on a plane and pray it wouldn’t crash.
It’s amazing what horror stories people tell you when you are about to move. The income tax is 30%! The public transport sucks! The streets are barren and empty, with nothing but sheep grazing around! The natives are racist and will murder you in your sleep!
All of the above, of course, is not true. But even the great man in the sky had his two cents. A month before I left, Christchurch (a major city on the south island of New Zealand) was hit by an earthquake. Barely a day after I arrived, he whacked it again. He also sent a giant volcanic ash cloud all the way across the Pacific Ocean, that had Qantas, Jetstar and other airlines grounding their planes. Luckily, I was travelling on Singapore Air, which isn’t put off by a little dirt in the air.
No sign of an ash cloud!
As I stepped through the gates at Changi Airport, leaving my family behind, the enormity of what I was doing hit me. I had left on fairly long business trips before, but what I was doing now was starting a new life in an unknown country where I don’t know a single soul. (which was kind of the point of it all) Not being the religious type, I didn’t ask for a divine sign. However, I got it anyway. As I stepped into the departure lounge, I was greeted by oodles and oodles of japanese school girls! Surely this boded well for the trip ahead. Unfortunately, they were put in a separate part of the plane.
The flight from Singapore to New Zealand takes 9.5 hours. That’s a lot of time to spend cooped up on a plane. Fortunately, I was on a night flight, so I slept through most of it. The in-flight entertainment movies were meh. I only watched the Green Hornet. I really loved my Shure e2c earphones as they managed to block out a great deal of the engine noise, as well as all of the chatter and baby sounds.
When I arrived at Auckland International Airport, the first thing I did was grab a pre-paid SIM card from Vodaphone, complete with 50 MB of 3G data. I figured that as long as I have Google Maps, there should be no problem! After that was the trip to what I now affectionally call…
The Housing Debacle
I arrived at Lantana Lodge, to be greeted by a very cheerful Japanese guy. He looked up my reservation and exclaimed, “Wow, you have the luxury room!” Sounds good right?
Well it turns out that Lantana Lodge is a hostel, with about 30 people (at the time) living together. My “luxury room”, was a double bed and a mini fridge in a room. That was all. No bathroom, no wardrobe. The toilet facilities were communal, as was a general rec lounge and kitchen. Too tired to complain, I crashed to bed (which was incidentally very high quality, especially compared to everything else) and slept till about 7 when I snuck out for a kebab dinner before getting myself organized.
It was lucky that I slept in the afternoon, because at 3am, band practice was in full swing, replete with drums, guitar and singing. Unfortunately, they weren’t very good.
After one night there, and much complaining, I was transferred to Quality Hotel Barrycourt, which was the polar opposite from Lantana Lodge. This was a full-fledged hotel. So from communal toilets, I progressed to a private bathtub with full toiletries provided. I also got a kettle with free coffee, a 32″ flatscreen TV, and an ironing board. The food at the restaurant was also pretty good.
This weekend, I have been shifted once more, this time to 45A, St Georges Bay Road. This is a small 2-bedroom townhouse which I am sharing with a young English couple who are also here for work (but for a different company). So now I have a full kitchen, living room with TV and comfy leather sofas, and pretty much everything you would expect to have in a house. I may opt to continue staying here (at my own expense this time), but on Monday, I will be viewing a studio apartment in town which I may move into.
Much better accommodations!
I was expecting things to be different in New Zealand, but it’s a bit hard to predict exactly how that manifests. The big shot to the liver of any game developer is that the Internet is rationed! All the internet plans have a set amount of data which you are allowed, after which you must either top it up or proceed at excruciatingly slow speeds. That puts a severe cramp on how many games you can purchase of Steam. Bit Torrent and the likes is of course, completely out of the question, not that I ever indulged!
Kiwis don’t carry much cash in their wallets. Almost every transaction, even ones as small as a couple of dollars, are done with the swipe of an Eftpos card, which is something like a debit card. The only time when you use actual physical cash is for bus rides, and even then, there are stored value cards much like what we have in Singapore. New Zealand is well on the way to becoming a paper-cashless society.
Another peculiarity is that we don’t like color here. Indeed, on the streets, all you see is blacks, greys, dark blues and the occasional olive drab. Perhaps this is in support of the All Blacks? Whatever the case, it made my bright cyan ski jacket stick out like a sore thumb. So one of the first few things I bought here was a nice black leather jacket. The leather’s so soft and keeps me very warm, occasionally too much so when the sun is shining. I’ll probably look for a hoodie as well, because that’s what all the Starcraft pros wear!
The weather is decidedly mild, with temperatures between 12 and 17 degrees Celsius. It is winter now, and that means rain. When I say rain, it’s not the torrents like we have in Singapore, but very mild drizzles. One night, I made the fatal error of carrying an umbrella. While the raindrops themselves are very light, the wind is crazy! It was a major task just getting the brolly to behave. No wonder everybody else would rather walk in the rain!
The Gameloft office is pretty big, spanning two floors. It follows the japanese layout, i.e. everybody in an open space, no cubicles and no rooms. I’ve been given a pretty sweet rig, i7 processor, double monitors, etc. My programming lead a pretty cool fellow. We had the following conversation:
“So, have you done game programming before?”
“Yes, for about seven years.”
“OH YES!!! Thank you!!!”
They are evidently facing the same labour problems we have in Singapore, possibly more acutely. The only major gaming companies here in Auckland are Gameloft and Sidhe, so the industry still has a ways to develop. I searched for a local IGDA chapter. I ended up finding NZGDA, where I read the following forum post, “New Zealand is a bit slow. Things will pick up in 10-15 years”. Oh my!
That being said, I managed to find the “underground indie game developer” group that meets up monthly. Maybe I can get some good networking action there! Some guy from Zynga is supposed to be coming to give a talk on the 26th.
Where to go from here?
Well, first I need to find permanent accommodations, and get my sleep cycle sorted. After that, and my initial 360° exploration of the surroundings, I can finally settle down and perhaps get some work done on Darwena, which as been languishing in the sidelines for way too long. I’ll also be looking around for new activities. I found a quaint little coffee shop on Parnell Road (an old part of town) which would be excellent for an afternoon of coding. Things are looking up indeed!
Posted: April 10th, 2011 | Author: Eugene | Filed under: Soapbox | No Comments »
Interested in a Job?
With my recent foray into realm of job-seeking, it seems I have come full-circle and experienced all sides of the interviewing table. I have been an educator, a contractor / freelancer, recruiter and now a job-seeker. Yes, the table is indeed rectangular as all good and proper tables should be. (Don’t believe any of that round table nonsense!) I figured I might as well write on each of these perspectives to provide you a more holistic picture. Happiness and satisfaction, however, are not guaranteed.
How many game industry veterans do we have in Singapore that are willing to lend their wisdom? The answer is zero. So who are teaching these game courses? There are three main types. The first is the educator that is not from the games industry. They basically read a lot of books, try to get the gist of what it’s all about, and do their best to pass it on to the students. This group was especially prevalent six years back when these game courses were just starting to emerge.
The second group is your imported talent. Experts you bring in from overseas to train the local younglings. I am guessing that they are pretty expensive, and you would tend to see them more in degree courses than diploma ones. I do not know the mettle of these foreign talents, never having the chance to be under the tutelage of one. I would expect them to be above average given the credentials I have been seeing.
Lastly, you have the half-baked potatoes. This is the group I belong to. Sure, we have some experience, but wouldn’t call ourselves experts by any measure of the word. We are simply the only locally available alternative. There are a bunch of us roaming about between the institutions, and most teach on a part-time basis to supplement our other work. Oh, wouldn’t it be wonderful if we had retirees like say, Miyamoto, to spread their wisdom.
Right, teachers are a problem. The next problem is students. Unfortunately, the words “game development” are so interesting that we attract quite a crowd, most of whom are more interested in the “game” part than the “development” part. The other sad thing is that these students are under the impression that once they graduate and have their fancy piece of paper, they are industry-ready. The sad truth is that you are only really ready if you are self-motivated enough to pick up skills on your own. An optimistic approximation would label about 20% of the cohort of a typical diploma program as industry-worthy.
If I could fail the other 80% and save future employers needless pain and frustration, I would. Luckily for them (the students, not the employers), I was told I cannot. The almighty bell-curve has to be respected. So what happens? Curriculum gets watered down, so that these students can “pass”. Life becomes easier. 3D graphics too hard? Let’s just stick to 2D, shall we? Maybe you don’t really have to learn A* when a turn-left algorithm will do? The end result is a lot of complaints from students and industry alike that the courses are not providing enough foundation. *sigh*
If you are a student and wondering why it’s so damn hard to get into say – Digipen, this is the reason why. They are weeding out the 80% who really have no place in a games development course. Harsh, but you have to respect them for it. At least they have standards.
We already know the curriculum woes that result from a weak student body. There are also other pressures, like pressure from industry. These well-meaning institutions decide to take the sensible approach and go out to ask game development companies what they need. What do they get in response? Everything under the sky! We need Unity3D, C++, C#, Java, Flash, Objective C, Torque (RIP), console devkits, UDK, etc. Every company has different requirements, all of which
evolve mutate with time, and given that most course managers don’t have a grounding in the game development process, what are they to do? Who are they to turn to? Hell if I know.
I have helped a few of my clients to interview potential employees in the past. Bear in mind that these are all SMC’s (small-medium companies), so it might not apply to the big boys. Recruiting in Singapore is hard. Why is it hard? Because there is nobody out there! You can put out an ad in the papers or any number of job recruitment sites. What do you end up with? A ton of resumes from generic people who have no game industry experience, no game-related academic qualifications, and likely don’t even play games themselves. This is even so if you highlight and boldface these as requirements. Oh, and you also get a healthy number of applications from India and China.
So after you weed through the mountain of resumes and find the handful of people who might have some inkling about what the job is about, you call them in for an interview. There are many points of failure in this process. The first hurdle is confidence. We get interviewees that are so nervous and/or quiet that we feel sorry for them. Do we hire them because we feel pity? No.
Then there’s the portfolio. There is no excuse not to have a portfolio. If you are a programmer, write some code. If you are an artist, draw something. We don’t really care if you have a degree or a diploma with 3.8 GPA. We want to see what you have done and how you think. That is all that matters. If you don’t have it, you don’t matter.
After that, there’s the test. I designed a practical programming test for one of my previous clients. I thought it was fairly straight forward – programming 2D behavior with the rendering, input and general framework already written for them. Sadly, very few even got past the first step of the test, which was to call a function which I wrote for them, in response to an input event. Do I really want to hire anybody who can’t even figure that out in an hour?
I recently went through the experience from the other side. A potential employer (quite a large company) gave me a written test. It was basically on optimization (by optimization we mean bitwise operators), C++ and OpenGL. It was a two and a half hour test, and was fairly challenging. I shudder to think of the applicants who went through my test sitting for this one. Maybe most people don’t make it through this test? Apparently so. I have an interview on Tuesday.
While the employee market is sparse, the intern market seems to be thriving. Almost everywhere I go, I run into interns. Oftentimes, they are my former students. You would think that it would be a simple matter to hire interns, train them up, and hire them as full time employees when they graduate. Not so easy! There’s this thing called the Army which sucks up all these interns right after they graduate and holds them in stasis for two years, possibly with brain decay. It turns out that females are immune to this monstrosity, but they are so rare in this line of work. So if you are a game developer of the fairer sex, know that everybody loves you, and not just for your stunning good looks.
I entered the job market with two objectives in mind. First, I want to move overseas. Second, I want to move into game design. Any job that fulfills either criteria and opens the possibility of later expansion into the other, I will happily entertain. With that plan in mind, I jumped.
The Game Design Path
There are precious few companies in Singapore that are hiring game designers AND have some sort of way to get me deployed overseas in the future. Most of these are the bigger boys. Out of these large wealthy companies, I only fancied a couple. This is largely because I went for interviews with a lot of these companies in the past and the culture did not appeal. Why did I go for these interviews, you might ask? Headhunters called, and as long as somebody calls, I’m always happy to talk and gather intelligence. Well, out of the two that I kind of liked, neither were hiring designers. I sent my resume in anyway, and received no response. They are probably snickering away at this crazy programmer who thinks he’s a designer.
The only other company I approached was one whose culture would allow me to travel. The nice people there did respond, and helpfully suggested I look for Tech Director positions or something more befitting my experience. After I explained the whole game design spiel, they probably felt I smell too funny to hire. What they did tell me is that they felt I would probably find myself dissatisfied with entry-level game designer salary as compared to what I can draw freelance, and end up leaving. I have to admit that it’s a very good rational reason, given that I’m Singaporean, and all Singaporeans love their $$$.
The Overseas Path
I discovered that there are international recruiting agencies that cater specifically to the game industry. That certainly wasn’t there the last time I went job hunting. So I signed myself up and a nice British bloke called me after a day or two to clarify some details and lay some expectations. “Very professional!” I thought, much impressed. I never heard from him again, ever.
After similar experiences from a couple others, I can unscientifically conclude that recruitment agencies do not work. Well, not in this way anyway. The only recruiters that have managed to get me job interviews fall into two categories. The first is the kind that come and look for you (i.e. the headhunters). The second are those that have a vacancies that they are looking to fill and post ads everywhere.
Recruiters aside, where do I find job vacancies? Typically they are places like the Gamasutra job section, the game development group in Linkedin, personal referrals (God bless their souls), etc. One thing about these vacancies is that most of them are looking for people specifically in the States, or specifically in Europe. Why? Because immigration is hard. There’s a limit on the number of green cards issued, so overseas labor is unnecessarily complex to hire, not to mention the risk. In many cases, especially the smaller companies (which I love so much), I offered to offset some of that risk by relocating at my own expense. Gotta give some to get some!
This is not the end of my master plan. After my current project is wrapped up, if I still haven’t found a job that I like (never settle for a job you don’t like), I will travel myself to these Mecca’s of game development and see what I can find on the ground. This is the correct way to do it, or so I’ve found out. You can’t simply send out your resume and expect to land something worthwhile. Until I have freedom to fly, I’ll test that theory and get back to you if I disprove it. Not like I have anything to lose.
This is so easy to do that I am wondering why there are not more people doing it. Everybody wants to go “indie” and set up their own company, or they want to enroll in the rat race and be a cog in some big corporation. Freelancing provides a great lifestyle, pays pretty well, and supposedly gives you no sense of security whatsoever. So why on earth would I want to move away from it? I’m bored, and I want change. Me and stability don’t see eye to eye. Me and challenge – best buddies!
So if you want to be a successful freelancer, what should you do? The first step is to find a full-time job. “What?!” I hear you cry. Freelancing is easy but it’s not thaaat easy. First you have to have the skill. You also need some sort of credible portfolio that includes published works. The place to get both is in a full-time job. Having had the fortune of starting out when the game industry in Singapore just came out of the womb, my first full-time job was a nearly unpaid full-time job. I simply treated it as school, without the school fees. Self-rationalization is a skill.
The next thing is hooking up with clients. How do you do this? Networking. What is networking? It’s basically talking to everybody and anybody you meet. Go to IGDA chapter meetings, drinking sessions, networking sessions, product launches. Dish your namecard around, let everybody know what you are doing but don’t solicit business unless a “mutually-beneficial opportunity” happens to surface. Just get to know people, preferably personally as well as professionally. Chances are, nobody will throw themselves at your feet begging for you to work for them. But wait two to five years, and suddenly you get this call or referral, and you know your efforts have paid off.
You will also need a website, like this one. From this website, you can see a good sample of the projects I’ve done in the past, learn more about what I do, and even what sort of person I am. To top it off, I have all sorts of useful essays on things that help in game development such as this, the article you are reading now. Do your search engine optimization and make sure you can get Googled. Link it to Facebook, LinkedIn, and whatever other social networking thing you have. Be active and keep it current but do not spam useless stuff. You have no idea how many people have contacted me simply because of this website. Sure, some of them are weirdos, but most have some form of legitimate business to conduct.
Now that you have the clients, you have to manage them. The secret to freelancing successfully is to always have 2-3 projects ongoing at any one time. If you desire some measure of stability, one of those projects can be teaching at an educational institution. Why multiple projects? If you have been doing your homework and developed your skill, you should now be able to work many times faster than the average grunt. A lot of the time, however, will be spent waiting. Waiting for art, waiting for approval, waiting for design decisions, etc. So while you are waiting, why not do another project? If I work full-tilt, 3 projects are not a problem, and I don’t even have to work weekends (most of the time). Sometimes (like now), I drop down to one, just to have breather and smell the roses. Quality of life vs quantity of money – you decide.
Now the biggest secret behind freelance success? There are no other freelance game programmers in Singapore! There used to be a couple of others around, so we could chuck excess work back and forth, but the others have since found other pursuits and now I am exiting as well. OMG!!! Can you say power vacuum?! That said, there are companies that offer contract services, but people often reason that freelancers will be cheaper than hiring these companies. Partially true. We don’t have overheads. Office rental is – $10 a day for a venti vanilla latte plus a snack at Starbucks. Don’t have to pay snooty employees. Nothing!
At the same time though, don’t undercharge. A student once asked me how much I charge per project. I said it depends on the project and it’s a trade secret anyway. The real answer is that it depends on demand. If you are getting more jobs than you can handle, charge more because you are obviously too damn cheap for the value you provide! It has less to do with how much you think your time with worth than how much they think your services are worth. I also like to charge per feature rather than per hour. This lets the client pull things in and out of the project as it progresses, as they are wont to do anyway, and you get to quote them on every single change. I also charge less for games that I think will be particularly portfolio friendly (here’s looking at you, giant robot with guns game – you heartbreaker!), or that I simply find more fun to work on. My business, my rates!
Posted: March 6th, 2011 | Author: Eugene | Filed under: Soapbox | 3 Comments »
Where do I begin? I am not a religious person. While I do not believe in God(s) per se, I do not deny that there could well be something out there. I also recognize that it is beyond my ability to determine what is what in the great beyond, so I choose to simply put that question to the side. Perhaps one day, when I recline comfortably in my grave, I will be able to shine some light on that issue. Today is not that day, or so I hope.
So what do I believe in? Some people believe that they are put on this Earth for a purpose. More power to them because it makes life or any other endeavour so much easier when there is at least a vague direction to follow. I do not entertain such a luxury. I believe that it is up to me to find my own way, purposeful or not, and live through life with no regrets but my own. I refuse to live at another’s whim, and would not expect another to live at mine. True, I do owe a great deal to a lot of people – family, friends and other people in my life. However, as much as I am indebted to them, I claim this life for my own and reserve messing it up as my own privilege.
I began my working life in a small company called Coaster Computer Services. My boss, Victor, was a shrewd small-time businessman who had me creating software solutions for other small businesses. He is also the man who had the ability (which he often exercised) to use the word “fuck” in the most gentle, non-vulgar and non-offensive way possible. I learnt a lot under his wing including how to deal with clients and how to develop software from design to delivery and beyond. As pleasant as working there was, I had far more ambition (in other words, I wanted more money, more fame and more glamour) than that job could offer and through a series of events moved on to the next phase in my career.
From a small-time software house, I spread my wings and starting working on multi-million dollar projects as an employee of IBM. I was part of the business consulting group, working in a large team spanning four continents creating and deploying backends for the largest banks in the world. I was part of the working class, with my formal (by today’s standards) shirt and pants, walking down the street to work with millions of other people just like me. The hours were gruelling, with team members turning up for work at the office at practically any time of the day or night. I was having the time of my life.
The group I was in worked under the absolute best project manager I’ve ever had the pleasure to work for to this day. His name was David, a former techie turned manager turned director. He was our guardian angel, protecting us from office politics, enforcing food and rest when we overstretched our limits and basically steamrolling through anything that got in the way of us doing our jobs. He is well-respected, probably filthy rich and obviously enjoyed his job. One day, I had a good look at him, where he was in life and the lifestyle he was living. Was this the role-model I could aspire to emulate ten or twenty years down the road? I looked deep into myself and realize that the answer was no.
It is at this point that I really started to understand myself, life and the world in general. Money, I realized, was only a means to an end. What is that end? Personal satisfaction. Many people go through their lives slogging through work mindlessly so that they may raise enough money to “buy” happiness in the form of material creature comforts and a better quality of life. While I am all in support of material luxuries (yes, I’m no Gandhi), what disagreed with me was the slogging part. Why spend a majority of your life doing an activity that you do not enjoy just for the sake of being happy during whatever time is left over? I decided to cut to the chase. I’d be happy first and worry about the money later.
I was always fascinated by video games, both playing as well as creating them. (though admittedly mostly playing them) In my university days, I had three main priorities. My top priority was… competitive Scrabble. Yes, I am and have always been nerd, thank you! We had a great team that trained hard together. The camaraderie was so great that I felt I was a significant part of a bigger whole. We played, we conquered, we celebrated. My second priority was the Leviathan. The Leviathan is an online text-based roleplaying game. Think of World of Warcraft but without the graphics. While I played that for a while, I soon went into development, becoming a Wizard (i.e. a coder) and created new areas and mechanics for the players. It was set up so that the development environment was part of the live environment. It is a coder’s paradise with the instant gratification of player comments and complaints as they explore your new creations and their moans of anguish when you inadvertently crash the whole game. My third priority was scraping through on studies so that I actually got my degree. I hardly attended any lectures or tutorials but studied on my own as well as in a study group. I admit this was mostly done so that I could devote more time to my first two priorities.
Alright, back to the career bit. During my days in IBM, I did somehow manage to eke out some personal R&R time. I played my first ever MMO which was Dark Age of Camelot. In this game, I had the pleasure of making the acquaintence of a fine fellow called Alvin. Alvin himself, was in the fledgling game industry in Singapore. He set up his own company, Nexgen Studio, and just simply went for it. With a mish-mash of interns and recent graduates, he managed to produce an FPS demo. It sucked (sorry Alvin!), but it was a good start for a business still in its infancy. Like all other fresh-faced developers with delusions of grandeur, he wanted to create an MMORPG. (admit it, everybody goes through that stage) He had a business plan, a design, and even a comprehensive background story. He showed me what he had, and I promptly quit my job and turned up at his doorstep to work for next to nothing (not that he could afford to pay anybody at that point). He expressed amazement at encountering somebody as insane as he was.
We worked hard for the next year and a half. Though the going was tough, it was also a lot of fun. I got free reign to do just about anything ranging from project management to marketing to meeting VC’s to programming. It was a blast. I gave the company a year to make or bust. Much to my chagrin, neither happened. Instead, we merely survived – somehow managing to subsist without going anywhere. It was a hard thing to do, but I informed Alvin that I was leaving the company. By then, we were good friends, almost brothers-in-arms. As I mentioned at the begining of this whole tirade, I live this life for nobody, good friend or no. So we parted ways and I went into the glorious world of freelancing. I am happy to say that after I departed, the company has done quite well for itself – a happy ending afterall.
Why did I become a freelancer? The honest truth is that I wanted to set up a company of my own but was too chickenshit. Instead, I would do the market research and find out how other companies operate from the inside, examine their challenges and mistakes, and learn from them while they footed the bill. Yes, I do not deny that I am an evil genius. You would think that making a living as a freelancer is difficult. In truth, it is disgustingly easy. All you need is the will to work hard and some semblence of discipline to maintain professionalism. You do your networking; shameless self-promotion. You make sure you do a good job and that your clients are satisfied, and word will spread. Business will flourish.
The lifestyle is great. I spend my days coding or meeting interesting people. I am seldom confined to an office for more than a couple days a week. I can truthfully claim to do game development in various branches of Starbucks Coffee and Burger King around the island. If I need a breather, I can simply take on less jobs. So it seems I have attained game developer nirvana. That is a bad thing.
If there is something that I have learnt about myself, it is that I dislike being comfortable. The freelancing job fits me quite well because I can flit from place to place, project to project, and it is always different. I learn new technologies and techniques along the way and all is good in the world. However, lately, I have been finding it increasingly difficult to sit in front of the screen and do actual work. If I were the typical Singaporean, I would grit my teeth, force it through with sheer willpower and get the job done. Obviously, having just said that, I did exactly the opposite. I have been spending a fair amount of time in introspection (i.e. sitting around and doing nothing). There is a reason for my failing drive and that reason is not laziness. I have always been lazy and that has never gotten in the way before simply because I love my job too damn much. So what do I want out of life and why does it feel like my current direction is off-kilter?
I definitely still want to make games. The original plan was to set up a company so that I can make the games I want to make. After all, I have already learnt so many lessons from all my previous suc… clients. Why not put them to their intended use? Have I not suffered through all manner of brain-dead or ludicrous “designs” and “concepts” that I have earned the right to make something on my own? To be honest with myself, I don’t even care if it sells or is profitable. I am past caring too much about money other than the occasional need to eat. Yes, there is a flaw in the master plan that I failed to perceive when I set out on this whole venture. As Steve Jobs has said, this changes everything… again.
If I were to set up a company, I would be too embroiled in administration to be usefully engaged in the development process. Sure, I would have the privilege of being the boss and well… bossing people around. “Yes, you should do this. No, don’t do that. This is the way to do it… Where’s your company spirit? Worship me because I pay your salary!” The truth is, as has been blatantly demonstrated to me, management messing around with the development process too much is a bad thing. Bad for the project, bad for the team. I would never have the fine-grained control over the project that I cherish.
To add to that, I want to do other things as well. I would love to learn how to draw/paint, play beautiful music, engage in creative writing. I have no illusions of being “good” at any of them, but these are indulgences rather than core skills. I want to experience life to the fullest and take in all that it offers me and then some. I want to always keep moving and never stop till day I cannot move anymore. For all this, I would be willing to be the serf instead of the ruler. Who in their left mind would not?
With all that said and done, where do I go from here? I have decided on two long term objectives. First, I want to make the shift to game design. Second, I want to get out of Singapore and move to somewhere completely different. Make no mistake, Singapore is a great place. It has low crime, good infrastructure, excellent quality of life and is probably one of the easiest places to make money in. However, with 6 million people crammed on a little red dot, all chattering and yammering as they go through their lives like automatons… I need a change.
Ultimately, is that not what life is all about? I pride myself on following through on arbitrary decisions made after a period of daydreaming and being non-productive. You cannot chase dreams if you do not have any and one dream is as good any other, no?