Sunday, February 28, 2010

Shady techniques

Post arrives a little bit late this week. Yesterday we had a party in Highstreet, a club in Belgium. It has been ages we went there. Last time "Push me, satisfact me" was on the radio, I didn't had a daughter or girlfriend, and the average videocards didn't had pixelshaders yet. That must have been 140 years B.C. or something. Let's do some history.

Lightmaps
I was already trying to make a game those days though. MD2 morphing animations, terrain rendering, and fixed lightmaps. Wait a minute, I did attempt to make a dynamic light with shadowMapping back then, but it was way too blocky for practical usage. Like most other games, lightMapping was the way to roll. Quake 1 was one of the games that made first use of it. Calculating realtime lighting for multiple sources was way too heavy those days, so instead game maps ussually had their lighting pre-calculated by "baking" an image with all light information. This image(lightMap) was typically made while creating the maps and it could take hours to calculate such an image. The shot below was from my previous engine, using "radiosity normalMapping" (fancy way to do lightMapping). The light spots on the ground and shady walls were all calculated and baked into an image in the map building phase.

LightMaps did service for many years. Quake 1/2/3, Halflife 1/2, Goldeneye, just a few examples. And it is still used. For a good reason, because once the image is created, it is a very simple and high-performance way to do quality lighting, including indirect lighting (ambient / global illumination / radiosity). In fact, most games still cannot do without because calculating ambient light at realtime is still extremely difficult, if not impossible for some scenario's... although CryEngine 3.0 may bring a revolution in ambi lighting soon...

Ignoring the indirect light portion is not a good idea either. The pitch black shaded regions in Doom 3 received many criticism. Its graphical competitor Halflife 2 looked more natural. However, Doom3 still had an important role when it comes to graphics evolution: realtime lighting with correct shadows. Halflife 2 may had the realistic renders, it still used the ancient lightMapping method, bringing some serious limitations with it. Popular bumpMapping shaders do not apply very well on a lightMap since this image only contains colors (light that falls onto that pixel), but not info about where it came from (direction vectors). Valve did a smart trick with their "radiosity normalMapping", but in the end it's still an approximation, not true correct lighting.

But more important, LightMaps are static. That means they won't change when you move a light. A day/night cycle, shooting lights, or using light switches is not possible with lightMaps. You have to recalculate the map whenever something changes. That is not so difficult, if it wasn't it takes seconds, minutes or even hours to do so. Updating lightMaps realtime = too slow. Unless you do low quality lightMapping maybe. I tried that, with success, but it's quality is way too low for accurate lighting. It can be used for dirty ambient lighting maybe, but not for direct lighting. Swinging your flashlight for example requires a spotlight with sharp shadows, but you can certainly not achieve that with low quality lightMaps.


Shadowmaps
Like I said earlier, ~eight years ago I tried dynamic shadows with shadowMapping already. This is a relative fast way to calculate shadows at realtime. Here's the idea: in the background, render your scenery from a light-point-of-view. Imagine you are a lamppost, put the camera in it, and render the street below you. Every pixel you'll see is litten by you. All others are shaded. We do not render colors, but the depth (distance between light and pixel) into a target texture. This depth image can now be used for lighting. When rendering your normal scene, check for each pixel if it was litten. Simple, if the distance between that pixel and the lightsource is equal or smaller than the projected depth image pixel on that location, it receives light.

This technique is called shadowmapping. Nowadays hardware is fast enough to generate multiple shadowmaps hundreds of times per second. And because images lend them selves for blurring, it is possible to create "soft edges". Another problem with Doom3 were the razorsharp shadow edges. In reality shadows are somewhat smoother due light scattering and stuff. Doom3 did stencil shading. Basically the CPU calculated silhouettes around each occluding object/surface and cut them out the buffer to prevent lighting behind them. ShadowMaps can be blurred more easily, and another advantage is the hardware acceleration. Instead of using the CPU, shadowMaps can be made entirely on the specialized graphics GPU. Well, no wonder that most engines are using shadowMaps these days, and so does mine. Here's a shot of my first test results, 3 years ago already. Notice there is no ambient lightig in the dark sections.


Cascaded Shadowmaps
~Eight years later, I still have that "blocky shadows" problem though. I'm not using lightMaps or fixed OpenGL lighting anymore, but shadows mapping techniques still tend to be "blocky" when distances between the lightsource and occluders grow. Makes sense, because stuff in the background receives less or none pixels in the depth image. This makes the shadows from objects far away from a light ugly or even invisible. Luckily there are always a bunch of smart guys who fix these things. Not me, I'm too dumb for all that mathemtical stuff. But at least I'm a persister, so after many Steve Irwin crocodile fights, I finally have "Cascaded Shadow Maps" working.

See that balcony railing shadow? Pretty sharp huh? It is casted by the sun, but the sun is pretty far away. With normal shadowMapping, this railing was probably invisible in the depth texture and therefore not casting any shadows at all. CSM is a technique to create multiple shadowMaps (see the 4 gray images at the bottom). The first one only covers a small section; the stuff you are looking at. The last image covers the entire scene. Now when shading, pixels pick the proper map based on their disances related to the camera. Neat, isn't it? Crysis and GTA IV used it as well to cast accurate shadows in dense (concrete) jungles. Allrighty, enough for this week.

Friday, February 19, 2010

Game concept document

Like Mick Jagger said, "you can't, always get, what you want". Programming can be very satisfying (for the ego) when conquering new techniques or reaching milestones. At other moments programming can leave you restless in bed with a displeased feeling. I was hoping to finish the skeleton animations this week, but I kept seeing artifacts, missing triangles, and broken legs as if Steven Seagal just went by. Luckily someone on gamedev helped me out a little bit. Did I already say how much I love www.gamedev.net?

I was also distracted by an article from the GPU Gems 3 book, "Light scattering as a post process". One of the effects I certainly want are light shafts. I know how to do it with shadowsmaps & quad slices, but this technique seemed way cheaper and easier to implement. But again, I wasn't pleased. It works, but only for background light such as the skybox & sun. As expected, it doesn't cast correct light shafts either, as the whole effect is just blurry streaks towards a lightpoint. I bet it looks cool when the sun shines through the foliage in a forest (Crysis had this effect), or when being underwater ("God rays"). But for a game that is mostly indoor, it's pretty useless. And not accurate enough to simualate the dusty lightshafts that fall through the apartment or corridor windows.

So, I achieved nothing concrete this week. Being grumpy already, the test-maps Í've seen thousands of times to try stuff like this also looked more ugly than usual. Depressing. I dried my tears and cheered myself up by implementing a cheap but effective motion blur (post processing) at the last moment. Not essential, but a nice addition to make the movement feel smoother anyway. And for a budget price. It still doesn't do motion blur on moving objects though, but that should be easy to add.

But hey! There is some good news as well. I'm making a "Game Concept Document", or whatever such paperwork is called. Anyway, it already contains more than 50 pages japping about gameplay elements, level design and the story. Nice to have such a thing if there ever comes someone with interest for the project. I'm quite excited about the story. The last year I made about six different stories, but each time it would feel "copied" or just not right after a while.

* Here's some advice: don't get blinded by your own enthusiasm. Write down the story. Then wait a few weeks to cool down. Let it read by a friend, and then judge again. Probably you're not that excited anymore. But if you're still in love... then you know you got it.

I would like to share my story, but even though I probably had zero visitors on this blog so far, I'm too keen on it. Every detail is a spoiler, and I don't want EA or others to rape it. Hard to prove this way, but I think it is quite unique. Most horror games contain the default ingredients:
- A lab experiment went terribly wrong, as always. Stupid researchers.
- The final boss is one cool/charming/wisely talking, bad motherfucker
- As a child you was abused / the mysterious youth syndrom.
- You was created by reverse biological engineering; you are your own grandma.
- All the enemies hate you, and want you horribly dead.
- The gates of hell (or dimension Xenoz 43) have been opened
- Open end... for sequel 2, 3, 4 and maybe 5,6,7 and 8.
But NONE of that! The whole game is a 'variant' on a well known existing story... You'll find out which one bit by bit. Things are not always what they seem, and who knows what is best for you? I'm sorry, but I won't give anymore hints.


At a particular day, the factory director said to his wife "Hey, let's make something!". "What my dear?", his wife asked. "I don't know. Maybe something with cars... or cigars. Just something!".

It's important to have a good story and game ideas as a back-up. It drives you into making concrete things, instead of keeping testing around with loose maps. I did a few hobby/amateur game (attempts) in a team in the past, but it would ussually get stuck in this phase. Everyone likes to add ideas, but in the end nothing gets done as nobody knows what to make exactly. Logical, you need a clear goal. So here it is, the holy grail of this project; the game concept document.

Saturday, February 13, 2010

Heads-Up for the Display

Hey, time for a weekly update. Carnival started, and probably 90% of the province Brabant/Limburg is already dressed up, drunk, and/or sharing the bed with the neighbour. But still no costume here. Coming up with a custume was ussually more fun than carnival itself. Last eight years we went as cheesepeople, grandpa's, Samual Jacksons, superheros (painted myself blue, weared "external underpants" like Batman always does, and called myself "Plutonium boy"). And previous year we went as a bunch of rockers.

But this year... Everyone is on vacation or busy, no brilliant ideas for costumes, and to be honest... Being packed together with 600 drunken idiots into a tiny bar with "hoempapa" music isn't exactly my cup of tea anymore. Maybe we'll do something tonight, maybe visit the carnival parade with my daughter tomorrow. Maybe I'm getting old and boring.


Maybe I was too busy with making that damn game anyway. Added all kinds of tiny things to make this game feel more like a... game. The monster in the maze finally tries to catch you, makes scary sounds borrowed from Doom3, and the earth trembles with every step he takes. When I tested it for the first time, it was quite impressive to hear and feel the heavy footsteps approaching while not seeing the enemy due the thick layer of fog.

The monster approaches me dangerously, quicker than I thought. With a button-bash mechanism I try to run as fast as I can, but then I suddenly bump onto a wall. Fuck, cornered! I turn around but its already too late; A big silhouette appears out the fog. A few more steps towards me... so I could stroke and give him a treat. Of course, nothing happens. My player doesn't have health yet, there is no GAME-OVER! screen. What an anti-climax. So, I added a simple health bar as well, and all kinds of crazy sounds fade in when the enemy approaches.


I'm not a big fan of extensive bars and meters. Come on, do you have a Head-Up-Display in front of your eyes that tell you how much cigarettes are left, how many percent there is left until you fall asleep? And how the hell does someone know how many bullets are left when firing a MG42 3.24 seconds?

On the other hand, HUD and bars can stimulate or encourage things. It's nice to see your stamina bar growing when your Magic Goblin buys a new potion. In Farcry I actually cared about coverage as I would peek continuously at the "stealth meter". In case of The Sims, the whole house would be full of shit, puke and starving Sims if there were no bladder/hunger/comfort bars.

At my work I learned to keep user-interfaces as simple and clear as possible. The driver doesn't care if there is 15%, 16% or 45% fuel left. He just wants to know when to refuel, so an indicator + beep is enough. Same thing for games. There are often many (invisible) factors that influence your stealth, speed, aiming or enemy resistance. But what use is it if the player is not even aware of it? Why bothering camouflage if the effect is nearly noticeable? In these cases, the HUD can be your friend.

For now, a simple health and "mental" indicator. No precise numbers though. If I would ask you how you feel, you won't answer with "64%" now do you? It's just "zuperb, fine, normal, not so good, or like shit".

Friday, February 5, 2010

a-MAZE-ing

Always trying to create good looking maps to test with. But as I'm not a very good modeller/mapper/texture artist, it takes ages and the end result still often dissapoints. That leaves me no time for developing other aspects of a game... such as gameplay.

So for a change, I created a big maze. An ugly simple map made of many corridors. To hide its uglyness, I used Maybelene mascara; a thick layer of fog. The fog does more than that though, it also hides a big threat in this claustrofobic world; a big, slow wandering creature. You can hear it, but you can't see it...

To be honest, that monster model has yet to be finished. Biggest challenge is writing a proper skeleton animation system + doing the skinning somehow. For now, a not-so-impressive, non-animated, Goldeneye look-a-like dummy soldier "ice skates" through the world. Making funny sounds (Halflife2 Combine chatter). But at least he finds its way in this mess. He's even kind enough to dodge me when I walk on his path, instead of rudely bumping me away. Meet mr."dummy":

Now I got to change this polite fellow into a monster.
- Proper pathfinding, picking logical points
- Realistic behavior when being unaware of you
- Scanning for threats
- Usings its ears
- Fuzzy logic when searching you without having a visual
- Predict your path in the maze
- Hurt you
- Being hurt
- Roarr! Moawn! Gorgle! Grrrr!
AI sucks in many games. Yes they might be 'smart' or tough, but I still feel an unfair balance. Either I can heal myself thousands of times in notime with neat medkits, and bulldozer over entire armies. Or vice-versa. Russians that pop me with a Makarov pistol while I'm lying in the bushes 500 meters away, monsters with ultrasonic hearing and X-ray eyes, and most annoying, Soldiers that happily continue their path just after being shot in the knee, head and balls.

This maze is a good playground for tuning AI. Make it difficult, but not unfair. The player must sense a learning curve, and use its skills. Not sheer luck, sixty medkits, or the auto-save. But most of all, let's see if this scenario can actually scare someone. I was making a horror game remember?

void TECH()
{
For the tech geeks, AI is done for most parts into Python scripts.
That means behavior is not fixed engine code. The engine just
sends events like "threat in sight", "path blocked", "second elapsed",
or "ouch, bullet in my head". The script does the rest. Except for
heavy duty tasks such as A* pathfinding, finding tactical spots or
updating the sensors (sight, hearing).
}
To finish this week, here a sneak preview of the maze-enemy. Although this won't be his final shape (look's too much like the Doom3 Hellknight). More next week!