Friday, August 3, 2012

Vertex-painting with Bob Ross

RLR (Realtime Local Reflections). A fancy word for... reflections. Realtime.

Did some interesting graphical enhancements last weeks. Realtime G.I. finally works a bit... got to be careful with such statements, getting consistent results that always look good is hard to achieve with G.I… Furthermore, RLR (Realtime Local Reflections) have been added for pretty accurate reflections on complex surfaces. I'll post about this soon, when I have some nice pics to show with it. And last but not least, we did some finger-painting.

Some artists make money just by throwing a bucket of paint or virgin menstruation blood on a white canvas. Random splatters, abstract stuff dude, smoke enough and you'll see what it means. Normal people however tend to paint / plaster their walls as smooth and equal as they can. Yet for games the artist has to be careful with repeating the same boring texture over and over again. For two reasons. First, even high-res textures still lack detail to vary enough, In reality, no matter how hard you try, even a white boring wall has some inconsistencies. Little drill hole here, crack there, darker spot in the corner, slight bump here, old brown blood from a squished mosquito, et cetera. In reality, you get all those details for free. But if we had to paste tiny mosquito blood decals or mini-holes on the walls in a game, it would take ages to finish.

Second reason, true realistic graphics suck actually. Why else do you think they need a light-experts, smoke machines and tons of make-up on a movie set? We want dramatic scenes, not clean white plastered walls we see every day in our own house. That's why we overdo it a bit with larger decals, damaged spots. And that’s also why I implemented an artist-throwing-with-buckets feature.

See that green wall? When our new artist Diego(from Spain, of course) showed me that texture, my first thoughts were "....". The wall looked boring (in an empty room I must say). But then again, what else do you expect from a green plastered wall? If you look in a new empty house, you won't see huge damage decals, random cracks, yellow pee stains and Mickey Mouse holes either. So basically, there was nothing wrong with this texture. But how a more dramatic look then?

Of course, you could add a few random details on your texture. For example, let's place a larger crack in the center, and paste some zombie vomit in the upper right corner, just for fun. Well, that might look good from nearby, but if you apply the texture in a larger empty room, it becomes a bit odd that this zombie vomits the same splatter every 3 meters at the same height. In practice, you probably won't use such a specific detail in your textures. That's where we have decals for. But also that bigger crack will become noticeable soon. Mip-maps may help you hiding this repeating pattern after a couple of meters, as such effects become more blurry in lower mip-map levels. But still... The magic trick for texturing is to apply as much detail and variation in your image, but without making it too noticeable repeating itself.


Entropy
================
As said, specific details should be added afterwards with decals. Decals can be placed everywhere, anywhere. Plus they can be rotated and scaled so you can reuse the same crack / hole / splatter / or whatever detail multiple times without the viewer directly getting aware of your dirty tricks. However, decals aren't always perfect either. Either you'll have to draw a LOT of variants, or use them a bit careful so you don't see the same picture being stamped on the walls over and over again. And using many decals may also have an impact on your performance. Also when you need to apply variations on a larger scale, you either need multiple decals or very large textures.

Since half a year or so, Tower22 has Vertex-Painting tools. You can draw(override) pre-baked occlusion values with those, in case you want to make a corner darker for example. But it can also be used for "Entropy". For each material, additional textures can be defined so you can manually draw variations on your surfaces. For example:
metal > corrosion
Brick > painted parts / worn parts
Asphalt > holes / wet(water pool) parts
Pavement > Green moss between the tiles / displaced normals to make an uneven surface
Wallpaper > parts with paper peeled off / dirty parts

Pay attention class. Notice the dark wood tiles being repeated (the texture contains 4x4 tiles) in the background? Now look at the foreground. A different texture variant (a more pale looking one) was mixed in around the TV.

If you google “Entropy shader”, you’ll find some nice (UDK) movies. The basic technique is pretty simple, just mix(lerp) between textures based on the per-vertex weight values. It's similar to terrain rendering shaders that allow you to draw grass patches, sand or rocks. But to make it look more natural, smart tricks and masking textures can be used. Let's take a stone floor where we want to add moss. Where does that green stuff grow first? Exactly, in the gaps between the stones. So if you supply a heightMap somehow, you could fade in moss at the lower parts of the texture first. Here some pseudo code
// Fetch Stone textures (base layer)
stoneAlbedo = tex2D( stoneAlbedo, uv );
stoneSpecular = stoneAlbedo.a; // we stored specular in albedo alpha
stoneNormal = tex2D( stoneNormalAndHeightMap, uv );
stoneHeight = stoneNormal.a; // we stored height in the normalMap alpha
 
// Fetch Moss textures
mossAlbedo = tex2D( mossTexture  , uv * uvRepeatValue );
mossNormal = tex2D( mossNormalMap, uv * uvRepeatValue );
  
// Fade in moss. Intensity is stored in vertex.weight1.x
// Lower parts will get moss earlier
fadeInFactor = saturate( (1.f - stoneHeight + bias) * vertex.weight.x );
outputAlbedo = lerp( stoneAlbedo.rgb, mossAlbedo, fadeInFactor );
outputNormal = lerp( stoneNormal.rgb, stoneNormal.rgb + mossNormal, fadeInFactor );
outputNormal = normalize( 2.f * outputNormal -1.f );
// Reduce specular on parts with moss
outputSpecular = lerp( stoneSpecular, float3(0,0,0), fadeInFactor );
That's just one way to mix. You can also use the normal. If you want to add snow for example, surfaces facing upwards should carry more snow, while surfaces facing downwards shouldn't carry anything at all. Obviously, the way you mix depends a lot on the type of material you'll be adding.


Wall painting
================
For our green wall, we did yet another trick. The ideas was to have "repainted" spots. The kind owner of this room in Tower22 repainted some worn parts with a fresh layer of paint. The repainted parts should have a slight different(brighter) color, and the cracks should be less visible on those parts. As shown above, you could make a greenish "repainted" texture variant. But what if we want white or orange paint instead of greenish? Got to make yet another texture? Or how about customizing the color values manually with the vertex-paint tools?

If enabled by the surface shader, it's possible to adjust the Hue / Saturation / Brightness values locally. Again, by painting per vertex. The colors would get transformed from RGB to HSV, then we add/subtract to offset values given by the vertex weight values, and transform it back to RGB again. This allows to make the green wall darker, brighter, white, or pink for that matter.

Yet the initial "Hue drawing" results sucked a bit. By nature, weight values interpolate between 2 vertices. So if we painted the center vertex red in the pic above, it color would smoothly go from red to green, like a gradient. Unless you are Bob Ross, that's not how painting works. The transition from one color to another should be harsh. And if we did a quick & dirty paint job, we should see brush-streak patterns right? No worries, the GPU cooling fan is the limit.

To make more realistic transitions, you can make use of a mask texture. The values on this texture can be seen as an offset (or "height"). With a different vertex-weight, we paint this mask-texture (invisible) on the walls. The more intense, the higher the offset. --- offset = tex2D(mask).x - 1.f + vertex.weight.x ---
Then afterwards, we colorize it with the Hue painting tools. If the offset is 0 or below, nothing will happens. Once above 0, the color rapidly changes into its second variant, given by the custom Hue values.

No, this is not what you think it is. Just an artist throwing with buckets of virgin menstruation blood, that's all.

Pretty neat huh? With a relative cheap tricks (Hue manipulation & one extra read from a mask texture), we can customize this wall in many, many ways. And of course, this can be used much wider on a lot of different surfaces. All to "break the patterns". Preventing the eye from seeing the same happening twice in a scene is another step fowards into realism. Or at least eye-candy :)

Monday, July 23, 2012

Pick up Manual? [Y/N]

Instead of writing a long story about project management or Rock festivals & poop, why not do a shorter week-progress-report again, like in the old days?

Asides being a bit sick (thank you for passing the fever, girlfriend) in this stupid country where our summer days are filled with gray rainy clouds for 4 years in a row, last week’s programming was mainly focused on.... excited already? Real-time Global Illumination? Monster Inverse Kinematic animations? Superfast path-finding algorithms? Particle Accelerators?... Better, I programmed how to pick up an object! An old fashioned chipcard-key, to be exact. Spectacular. But don't think this was a five minute job, no no. If you programmed games, or red this blog before, you know that seemingly simple things often Have a whole lot more going on under the hood.

But wait a minute, didn't the "Minecraft" guy in the first T22 demo already pick up an hourglass or something? Yep, but don't forget pretty much the entire game-logic code has been replaced with state-machines and custom modules per object in the meanwhile. So, that code became obsolete, and ever since we didn't pick up flashlights or hourglasses again. But since Demo3 shall show some actual gameplay again, and collecting items is one of those basal game-mechanics... Mario picks up mushrooms, Doom Spacemarine grabs ammunition, Guybrush Threepwood collects all kind of crazy stuff, even damn Pacman already collected orbs. Or something. So, about time to fix this feature again. Including a real inventory screen, though we still need someone to draw the UI for that. Maybe our drawer Pablo knows a girl, but we'll have to wait till she finished her holidays and answers. Making this UI is pretty important though, because I program nothing without having good-to-look-at materials to work with. I'm not talking about that girl, I mean it requires textures, 3D objects, maps, sound or screen menu's to trigger my programming sparkles. Working with temporary “dummies” is like making a cardboard Gameboy for yourself as you can’t effort a real one.
Yet, the ugly "Pick-up" symbol is a dummy so far. Waiting to get it replaced with something good.


Picking up an object sounds like a pretty simple feature to program, and well, it is. But it's not just about "picking up X". It's about interaction with other (living) entities in the game-world in general. A keycard can be "picked up", a lever can be "pulled", an interesting thing can be "examined", a toilet can be "flushed", a guy can be "talked" to, or "smacked in the face" if it was a badguy. Just think about all the available actions you often see popping up in the screen in nowadays screens. These are “context-sensitive”. Stand near a door, and your player gets the ability to open it. The available action depends on:
- Where does the player stand? Where is he looking at?
- Is the player able to interact right now (depends on state/pose)?
- What kind of actions does the target-item offer? A brick probably offers different possibilities than a sexdoll or Enigma computer.
- Is the player allowed to perform action X? Does he have the keys / abilities, or triggered another event?
Questions, questions. And a billion different answers. In other words, "Picking up" is just one of the many interactions the player could have with an item. And how about the way it happens? Doom Spacemarine picked up ammo and chainsaws automatically with his toes when walking over. Guybrush Threepwood had to click an item, then click an action like "look" or "eat". And the (lazy & easy) modern way is to show a button symbol + available action when standing in the right position. Anyhow, there are many ways to interact, especially in a puzzle-like game as T22 where things shouldn’t always be too easy.

But instead of programming each possible action on its own, a more universal system should be programmed. And that's what I did. As explained a few times before, each object in the engine uses a DLL module that "controls" it. Physics, AI, sounds, how it responses on collisions, bullets, et cetera. And so a couple of interaction functions were added as well. Basically, it works like this:

Notice that this is the "normal way". Special objects may require different handling to get interfaced with, or automatically trigger something when approaching it (stepping on a landmine for example). Also notice that not each and every object requires its own specially coded DLL. Most "decorative" or "junk" objects use the same DLL. All doors or all key-like objects could share a single DLL as well, and so on. Each entity in the game has a list of custom properties that can be used to give some parameters. In case of “picking up”, we could tell the id-name of an item, it’s quantity, if it should be removed when being picked up, et cetera.


The last step in the figure is the actual event(s) happening when the operator(player) performs a certain action on item X. Of course, the actual actions again depend on whatever was programmed in that item DLL. It can vary from picking up something to deleting all files in the c:\windows\ folder. And sure, it doesn't have to stop there. There is a constant "ping-pong" between the operator(you or other guys with A.I.) and useable items, being hold together by the engine. For now, this Chipcard just disappears and adds itself to the player inventory. And from there on you should be able to examine it, and, maybe use it. On a door. Or... use your imagination. But we're not that far yet. Let's hope someone can draw a nice inventory first.

Saturday, July 14, 2012

Classified

As your Russian U-boats may have picked up, we're making another demo movie. Another? How about making the game itself, fool! Don't worry, unlike that Radar, the stuff inside the demo is actual game-content. Which also means it will be focused a bit more towards horror then. Don't expect a character running around with a weapon and doing complex interactions, we're not that far yet... Which is also pretty much the reason to make another demo; finding more people. At this pace, Tower22 will never be finished, or limited to a 4 store high retirement home.

Problem with T22 is that the intentions fall a bit between a full commercial game, and the relative simple/small Indy platform fun game. We're trying to accomplish a high quality horror game with good graphics, professional sound, and rich, lengthy gameplay. That goes far beyond the average Indy game that usually bets on just a few small sized, but addictive gameplay elements. Like… launching pigs as far as possible. Programming a 3D engine is obviously more work than a 2D (platform) engine. But also making the contents takes a lot more time. If someone mails me a sword made of 6 polygons with a blurry 128x128 texture, I'll send it back and tell him to shove that thing in his virtual ass. All assets need to look good, detailed, including specific dataMaps for all the shaders we have.

You don't have to be a genius to figure that will cost a lot of time, and filters out a lot of help-offers from artists that either have limited time, or not enough experience. That’s where the ridiculous budgets for nowadays commercial games come from. But here we expect magic to happen for free. Or as we would say in Holland “Voor een dubbeltje op de eerste rang willen zitten" (= not willing to pay more than a dime to sit on a first row seat)... Wouldn't it be smarter to adjust the requirements a bit? Accepting we're not a professional studio that can work 40+ hours per week on a game, having money for Freelancers and professionals? Tuning down the graphics a bit to get rooms and other contents faster done, having a wider choice of people who like to help? Making T22 less tall so it can be realized in a reasonable amount of time? Yeah folks, probably that would be a wise choice. But will I do it? Nah. Of course not.
Improved the glossy reflections a bit with higher-res sampling and blurry blurs. The small picture shows the actual reflection buffer. In the end-result, most of it dissapeared because materials such as wallpaper aren't really that reflective. Quite a lot effort for a stupid green dot below a litten wall.

About 20 to 30 hours are spend on T22 each week. Probably it would double if I would still live with my parents in a stinky bedroom + computer. It pretty much means that if I'm not sleeping, working, doing something with the family, drinking beer with friends, or sporting trying to burn that beer, pretty much ALL free time is reserved for T22. No TV, no early bed, no videogames, no daydreaming with a fishing rod somewhere, no reading books, no time for other hobbies. But I won't complain, because I love working on this project. Too bad other helpers don't spend that much time on T22, but I can't blame them as this project is not a lifework for them. Hopefully it will be one day :) Anyhow, the point is, if T22 wouldn't be the way it is now, I wouldn't spend that much time on it either. If it would be reduced to a simplified “budget” game, I simply wouldn't be motivated probably. And I wonder if the other artists would really like spend too much energy on simple stuff they can do with their eyes closed. Modeling a cardboard box instead of a dumptruck. Composing a monotome 8-bit background tune instead of an orchestra. All of us want to learn and to improve.

Sure, it certainly can be a relief to make something simple, with short-term results. It's like mcDonalds. No waiting, no bullshit, just stuff that hamburger, be happy, and feel like a ho 10 minutes later. But don't be fooled, also a 2D Indy game involves more work than you think. At least, if it's a GOOD one. Quickly setting up a playable framework might be possible in weeks or even days. But making the core elements work really well still requires attractive art, tasty sound and very well tuned programming work. I did quite a lot of smaller games before T22. But usually after a few months, I would get bored. So much effort, for such a small game that doesn't really, REALLY interest me anyway. Tower22 is a much more difficult/impossible task, but I know I will like the results, even if it's only demo movies for now. And that makes it worth to keep going.


Yet, we got to be a bit realistic. All cool and the Gang, but without an end-product or soon-to-be-realized goals, you still have nothing in your hands but dreams. And letting both the team and you (the gamer) believe in those dreams is difficult with such far-away targets. Why would one spend a lot of effort in something that is likely not going to be finished anyway? The irony is that if they all would forget that argument and just start and do a lot, such a goal would be suddenly a whole lot more realistic. But ok, that’s not how motivation works. I always tell the team it requires momentum to get things done. There is a big rusty iron ball laying in the dirt. If you start pushing all alone, you'll break your back. Instead, all of us have to push, at the same time. But once rolling, it's easier to give it an extra push to keep it rolling. Makes sense, but to get them pushing, I still need to explain them why they should push. Preferably I’ll provide sub-targets that are worth doing, even if T22 as an end-product would fail. Learning something new, making a monster you really like. And making a demo movie is also one of those things. It's always nice to show your friends or future work a little "portfolio" movie, right?

As for the longer-term, there are plans as well. But don't tell anybody, these are classified of course:
1.- If the next demo movie is good enough, I'll poke it to a popular games-magazine as well. Hopefully that will generate attention to a wider audience, which hopefully gives us more artists with talent + time on their hands. Because that is what we really, really need right now.

2.- Eventually even more demo's are made if needed. To use as testcases for certain programming tasks, to get more attention, and to please ourselves of course.

3.- Although the game is complex, it does not contain full CG movies, super advanced animations, tons of enemies, complete orchestras, dialogs requiring professional voice-actors and lip-syncing techniques, or ground breaking techniques. Just making the environment & a working engine is the biggest part.

4.- We won't make the full game right away. The plan is to create about one-third of the game (the easier sections first), and release it as an Indy, or even free, game. If received well, it creates possibilities for the second part. If people are wildly enthusiast, getting more (professional) help and a budget should be easier. And if not, a man has got to know when to stop.

5.- You can't buy luck, but money certainly makes things easier. If the progress on the first "episode" is finally going well, meaning we made a substantial part and I’m able to plan forward, I might open the doors for donations (via Kickstarter or something). That's probably not enough to drive cars and feed the family, but if I can pay a few bucks per asset, it certainly helps the artists to reserve some extra time for it.


That's pretty much the Battleplan in a nutshell. But before we get that far, we need to create some game content and that third demo movie first of course. Hey... any new pics from that Demo? I'd love to share everything, but there is a reason why game companies always keep mysterious: reveal too much and it won't be a surprise anymore. Then again, if you show nothing at all, you'll miss the audience as well. People won't wait forever!

Friday, July 6, 2012

Pooptales

Congratz with another football victory Espanol! Since almost half of the T22 team is made of sundried Paco Loco, I got to support them a bit (even though the bastards shattered our World Cup dreams two years ago in the grand finale).

Vacation is over again, time to sweat again till somewhere December. Did we do anything interesting past 2 weeks? Friends & I visited a rock festival in Belgium (Rock Werchter) and there we're some family-duties in Poland. I don't speak a word Polish, so all this ideal son-in-law does is drinking dad’s beer from the fridge. Nevertheless, I did some useful programming while drinking, and observed the remains of the communistic era a bit.
Realtime glossy reflections here by doing raymarching through 3D textures filled with the surrounding scene. Pretty cool, and it runs pretty fast on my 2008 laptop but... the grain artefact stinks like socks. The reason is the reflection is done on low-res buffers with low-res data.


Rock Werchter (though it's more about poop)
-----------------------------------
But let's tell something about that rock festival first. Came and left with a mixed feeling. The line-up was pretty great. To name just a few; Jack White, Elbow, DeadMau5 (not rock, but after hearing guitars all day, you know) and my favorites Cypress Hill and Pearl Jam. Didn't see but also there were the Chili Peppers and another favorite, The Editors. Cool and all, but I always wonder if those artists really enjoy what they're doing, asides living the life of a rockstar, big house, five cars, being in charge. I mean, for us mortals the performance sounds overwhelming and we audience feels flattered if Gary Lightbody sais "Iek haouw vaan joelie" (Love you in broken Dutch). But don't forget these guys play the same jingle every festival. Rapper B-Real is wondering “How he could just kill a man?!” for 20 years already. I guess most of them just play their hour full, say love you, receive their cash, fuck you, and then get out of there ASAP.

Nevertheless, Elbow was crystal clear, Cypress Hill made us feel a L.A. gangster for a moment, Bombay Bicycle Club was also surprisingly enjoyable, and especially Eddy Vedder gave a hell of a show and behaved like a real guitar hero. So, what's the mixed feeling about then? Well, it isn't the music. It's just that I'm not made for the whole camping shit around it (this festival takes 4 days). I enjoyed sleeping in tents 15 years ago being member of sort of a cheap equivalent on the boy Scouts, but those days you didn't wake up with beer-hangovers in a 40 degree sun-baked tent. You would get a (healthy) breakfast and explore the forest or something, instead of sitting in the mud & sun, waiting/hoping to get that headache disappear. And then the crown on the turd; back then our "toilet" (craphole) was shared with 15 or 20 kids, instead of 2.000 drunk-puking- diarrhea men. Do you know Pyramid Head from Silent Hill? Imagine his uh... Pyramid head being made of brown chunky turds, 35 degree Celsius, smiling at you each time you visit the toilet and forgot not to look in the hole. My girl asked me what happened to me when I got back home. “You know what happened to professor Brundle in The Fly?”, I asked here. You would get a fusion with the toilet contents if being in there for more than four seconds. And yeah, if you drink beer, toilet visits are hourly business. If not for pissing, then to empty your alcohol tortured body with one happy rectum bang, like a combi between Rambo on the M60 and the Probotector/Contra Spread-Gun.

All of that might have been bearable if I didn't have a sore back. Don't know what I did, but after a few hours already, the lower-back started hurting, commanding me to sit down. On the mud, pizza-plate, piss, plastic beercup covered ground of course. I came to see artists, not the legs of 80.000 people (although seeing that "forest of legs" around me with Deadmau5 in the air was quite a bizarre sight... maybe an idea for T22). Probably walking around with lot’s bags in Poland, sleeping on a couch, and sitting in a train for almost 20 hours (back from Poland) was a bit too much for my rusty back. Hey, getting a day older as well! Finally, maybe even the whining about dirty campings and a sore back would be gone if I was a true music lover. But I'm not. I listen and enjoy, but I won't shout, dance, or fall in coma when Michael Jackson enters the stage. Over-enthusiast people give me the creeps. So, on day 3 I decided to go home a bit earlier as planned.

Conclusion: Make your own private toilet with wheels, a coolbox, and a cylinder that can pull it up so you can sit, watch the stage, drink, and piss whenever needed. Or a more realistic solution, if you’re like me, just stay for 1 day only when your real favorite artists perform.
Don't mention the black dots, those are just flies. The same technique for Glossy reflections can also be used to sample G.I. and Ambient Occlusion. The low resolution and low amount of sampling rays still make it a bit... unusable. Tried thousand-and-one Ali Baba tricks, but usually the consequences are either bad performance, light-leaking, not suitable for large scenes, or all of it together.


Fear and loathing in Polska
-----------------------------------
Enough Pooptales, Poland then. The first half of the vacation we visited my girls mom and dad again. I'm not really their son-in-law by the way, we're not married (yet). Anyhow, it wasn't the first time, no big surprises this time, so I won't write the same stories about alcoholics, cozy country village-life, and other typical Polska folklore again. But if you are interested, check these earlier posts:
- Poland 2010
- More Poland, and Auswitz

Neither did we see much of the European Cup football tournament being held in Poland & Ukraine btw. Our (sleeping)train traveled through the south parts of Poland, away from the football cities. I kept my eyes open for ugly (Soviet) buildings & flats, which are of course part of the Tower22 inspiration. As said several times before, it's not that Poland is stuffed with half collapsing concrete monster flats and abandoned nuclear silo’s. For one reason, a typical Soviet apartment block isn't that high (8 to 15 stores), at least not here in Poland. Second, Poland evolves as well (luckily), so old crap will either get a facelift or disappears sooner or later. Third, most of the South-West country is filled with dense forest and agricultural fields instead of stinky industry-villages. And the south-central part looks pretty charming actually. In the summer at least. The words "Soviet-village" make me think of decayed concrete buildings, blackened by factory fumes, between graffiti covered metal skeletons of old trucks, tanks, play-yards, somewhere in an extreme cold snowy wasteland. Sure, the connoisseur can find such sights here, but most of the landscape here is made of rolling hills, forest, rivers and pretty charming villages with houses & yards that are bigger than the average Dutch house. Although I must say the winter transforms it in an ugly gray monster. Not that Holland -or any other country- looks that nice below a package of gray rainy clouds, but the lack of maintenance on the buildings and infrastructure reveals itself when the trees, busy street-life and garden barbeques aren't helping. No, for Tower22 inspiration you'd better visit Poland during the Winters. Or maybe autumn, my favorite time of the year.
My vacation photo's, dobre.

It's quite funny that working on a game like this makes you open your eyes. For one thing, I always try to keep track of how things get indirectly illuminated. You know, the ambient-lighting story. But also, from a more artistic perspective, you'll focus on things a normal person would ignore. People must have been thinking "what is that idiot shooting?", when I was taking photo's while the train passed a whole row of infamous large factory red-white striped chimneys that each self-respecting Polish village has. A local just walks by and doesn't notice rusty gas-pipes, graffiti walls or sober apartment blocks. The average Polish guy just looks bored, tired, or "dangerous" in the case of youngsters who still need to overcome their insecurities. Women keep their eyes on shops. Though smaller cities here lack exuberant shopping centra, so women switch over to their second favorite activity: watching & criticizing other people/women. Then a tourist would focus on the good stuff. Rich decorated buildings, mountains, historical remains, et cetera... if there were tourists. Who the hell visits a small Polish village? But my focus is on gray walls, containers, old mining factories, rusty signs, weird stairs going to dark corners in the street a normal person would pass, old train wagons, holes in the pavement, and the ugliest parts a building has to offer. The best sights are the ones where you wonder "why?!". Why are two different color corrugated metal plates used to cover that hole? Why is that door only 130 cm tall? Why is there Zebra-skin wallpaper in this little restaurant room that probably wasn't a toilet first? Probably due the lack of money and urgency to perfectly design things, you often walk into half-finished improvised, charming, erh, junk here.


Polish Urban mysteries
-----------------------------------
But honestly there wasn't that much new "cool inspiration". As said, Poland is cleaning up itself slow but steadily, and been there / done that. Although... a few things are worth a mention:

* The good old Air-Raid.
In a small village like Milowka, the firemen are usually handymen -or something else- doing the fire extinguishing as an extra (volunteer) job. So that means they won't be standby at the fire-station. Instead, the siren has to pull them out of their beds, pub, or whatever they were doing. It sounds quite impressive, and you know shit will hit the fan as soon as the sky starts groaning. Each time I visit Poland there is at least 1 big thunderstorm, and that automatically inherits forest fires, burning sheds, toasted electronics, and thus a cool air-raid.

* PKP, that is Polskie Koleje Państwowe, which is Polish State Railways
The Polish rail network is not (fully) controlled by computers yet. Most stations have two houses next to the track, being used to control the rail switches. One of them being old, deserted, graffifucked and with shattered glass. And another house, being populated with one person, usually an older woman, hanging bored out the window, watching as the train passes by. I wonder though, how often does this go wrong? It looks boring but it's quite a responsible job. Fall asleep, forget a switch and boom. In fact, Poland had a large train accident very recently, killing 16 people. And yes, the cause seems to be a “human error”. But back to those houses… Each time when passing by I wondered why they need a whole building for one or two grandma’s hanging out a window. What’s inside those things? Gigantic levers? Just curious.

* Mysterious towers
Another typical Polish sight nearby those train-houses; these towers;

What are those? First I thought about storage towers for water, coals or grain or something. But the windows on the sides reveal those are just hollow cylinders. Doesn't make much sense to fill these with water. It seems people work(ed) at the tops, but as what? You're not going to tell me they have yet another rail-control building. Operating two or four switches at a small village station doesn't require a house, another abandon house, AND a weird tower right?

* Blockwave gas-pipes
More railway fun, though I think I can explain this one. But enlighten me if I got it wrong. Quite often you can see thick, block-pattern shaped pipes along the railways in cities. Most probably those were/are gas or maybe even oil pipes. Smaller pipes going into the city, tapping from these main pipes? Or maybe transporting gasses/fluids between the stations and factories that are nearby usually. But why this block-pattern? So you can walk or drive under the pipe each 20 meters? Eastern Europe mysteries!

* Church rock
Not much of a mystery, but quite odd for a guy like me nevertheless. Dunno about other villages, but in Milowka, the church plays a song at 21:00. Each day. And each day it's the same song. Something about virgin Maria and the three kings. As you know, Poland is quite catholic (that's why the average Polish man is never drunk and paints like an angel). A church playing music isn't that special, but there is something about that tune. It doesn't sound like Quasimodo & bronze bells. It's trumpet music, sounding a bit sad and triumphant at the same time... A bit like a Saving Private Ryan tune. I like it.



Most of you probably won't give owlcrap about block-pattern gaspipes or why rail switches are controlled in a house, but I'll try to extract interesting little details for our game out of it. The world is full of (rusty) miracles if you look a bit further!

Saturday, June 16, 2012

The Hollow Man

The first and last post for June. Harvesting season started, and usually that means long days at work. Quickly programming and testing new machines, and trying to fix machines and the mood of their drivers when there are troubles. Quite a lot of work, but very rewarding if you see all your computer screens and automatic regulations doing magic with hydraulics and cylinders. Anyhow, time for a short break and another family visit in Poland. And who knows, maybe we can encourage our Dutch football team there! Although… winning with two points difference from Portugal… I think our orange dream ends early this year.

Busy, busy. Always a good diversion from the lack of progress on that other thing, you know, Tower22. Plenty of posts about a Radar Station, but how about n-e-w stuff hmmm? Let me answer this tactically… There are three kinds of progress: lot’s-of-talk (no progress), visible progress, and invisible progress. Let’s say we belong in the last category. Not that we didn’t make any visible progression. Several objects and textures were made, and I’m especially happy with the two concept-artists who joined and did quite a lot of drawings last months.


Making rooms
The main priority right now is to create rooms, textures, interior objects, and more rooms. Creating a few floors from the actual game. To get a good test-case for all the programming work, to get something playable. Unfortunately, that’s where the “visible progress” halts; it takes ages to finish a room. Not because it’s an insane amount of work to make a room + textures + objects (although at first when your asset library is empty, it actually is a lot of work), but because… because… everyone seems to be busy all the time. The ideas are there, the floorplans are there, also the concept drawings of room X Y and Z are on the table. The programming work is far enough to get it rendered and even “played” (walking around and stuff). And last but not least, each one knows what to do. So, what’s the hold up?

Two years earlier, I would make most stuff myself, or just borrow it from another game. Making rooms went a whole lot quicker, but of course, at the price of lower quality as I’m not that much of a 3D modeler or texture drawer. And you probably recognized some Halflife2 floortiles or footstep sounds ;). Obviously, if you want to make a good looking game, you’ll need artists with more talent to make each and every fart. Don’t underestimate the amount of things to make even for a stinky Soviet apartment interior. Several floor textures, wallpapers, decals, footstep-on-linoleum sounds, closet here, lamp there. Doors, kitchen, junk to place on that kitchen, and the list goes and on.

Count the assets

If you have a team of artists with sufficient time, you can relative quickly step through an asset list and create some momentum. With that I mean, once you made a few rooms, you can start reusing objects, sounds or textures for a next room so the development speed will accelerate. But Tower22 feels like a tractor running on Kentucky fried gravy stuck in the mud on a slope. Usually only one to three persons have some time do things in a week, so if two assets arrive in the mailbox each week while the total asset count is 20 for a room, it will get a looong journey. But unfortunately, that is reality at the moment, as most artists are busy with work (got to earn money right?), girlfriends, moving over to another place, and so on. And I wouldn’t be surprised if some just don’t really like to spend too much time on T22. Hey, I can’t force anyone. All I can try is to motivate them, and keep things going with clear short-term goals. But in the end, it’s their decision what they do in their free hours of course.

Maybe that’s the price I’m paying for asking talented artists. Students or less skilled artists are likely going to have more time (and will) to help you on whatever 3D model, drawing or other related game content. They are already happy they can help on a real game anyway! Skilled boys and girls on the other hand usually have their hands full on similar (paid / freelance) work. If you spend the whole day making 3D objects for Resident Evil 12, you probably aren’t that motivated anymore to make some more for T22 once you get home. I can understand that, and I’m not the pushing kind of guy. But at the same time this “permissiveness” isn’t really boosting the development speed of course. Should I take a step back, accept the fact you just can’t expect people who are skilled AND have a lot of time, and allow less talented people to help on the project? Maybe. A lead-artist who can guide and train them would be very helpful then. But honestly, I just want to see and hear quality, nothing less. Rather finish something with lower quality than nothing at all? No. All or nothing baby.


Progressbar.Visible := false;
Programming progress then? Quite a lot, but again, mostly “invisible”. That’s because a particular technique often needs a lot of preparations first. Studying the matter, pouring it in a multi-useful, clear way into the engine, expanding your tools so you can make use of it. And then finally apply it in a room and take a snapshot to show it (visible progress). Let’s give some examples, so you’ll know what I’ve been doing last months. For one, I tried to improve the performance. Implemented Unified Buffer Objects, made the loading times a lot quicker by using pre-compiled shaders, squeezed the rendering pipeline, and started on “Deferred Tiled Rendering”. I’ll be back on that in detail in some day. Either how, before you can implement it, you first need to know more about how GPU’s work, and “Compute Shaders”. So, support for OpenCL has been added to the engine. Actual Deferred Tile Rendering doesn’t work yet though, because may laptop is too old to perform required atomic operations. Hopefully the laptop finally dies by per accidentally dropping it in a potato harvester so I can get a new one from work hehe. Anyhow, the point is, even if Deferred Tiled Rendering had been implemented, you wouldn’t see any difference other than higher framerates (hopefully).

No, we won't win the war with photograp and rusty can objects. Nevertheless, also the little ones matter.

Second little thingy. I implemented AVI video streaming support. Basically you’ll read decode movie frames each time, then convert it to an OpenGL texture and apply it as usual. Thanks to some standard Microsoft libraries, the whole decoding part is monkey peanuts actually. But integrating AVI support carefully in the engine and tools takes some extra work. The goal was to import and use AVI files in exact the same way as any other texture. So that means you can apply movies on everything in the game. Computer screens, lights projecting a movie on a wall, animated floors, Monsters with television heads playing Tellsell, et cetera. Well, it succeeded. Yet it’s still “invisible progress”, as we don’t have a finished movie file to use yet :|


Another thing. Gameplay! All that talk about graphics always. Wouldn’t it be nice, also for the artists, to actually walk around in our rooms? Run a bit, make a jump, open a door, shoot something. You know, game stuff. A lot of programming work has been done here as well, but no end-results such as flying around with Jetpacks, solving Myst puzzles, or shooting smart monsters yet. What I did is making a “framework”. It doesn’t do anything, but using this framework you can attach a custom “behavior DLL” (a program) to each object or monster, or the game in general. These DLL’s decide what to show in the main menu, how to operate your inventory, how monster X should act and think, how fast your player can run, and so on. Every specific game detail will be implemented in these modules. The engine itself is just a toolbox that offers these DLL modules a lot of functions to do things (an “API”). Render something, spawn an object, play a sound, check if monster A can see monster B, et cetera. It works like an event-response system. The engine detects something, for example, if a barrel falls down and hits the ground. The specific DLL behind that barrel will decide what to do, and calls the API. Spawn particles, decrease health, play a “Bang!” sound, et cetera.

When programming these DLL modules, you’ll notice how much little details there are. Almost forgot… you need game rules right? Can your player jump or swim? How many times do you need Boss X in the balls before he dies? On which conditions does the “Game Over” screen appear? It all sounds pretty simple, as we have countless of games with comparable mechanics. Yet Tower22 isn't a shooter ala Half-life or Resident Evil 5. So, each detail requires smart thinking. I’m talking about paperwork. Milton Bradley (MB board games) weren't busy with sculpting Monopoly pieces or drawing board-textures. At least, the essence of their work was to write down brilliant ideas. Addictive play, innovative understandable rules, and how to make the perfect game to transform cozy family nights into a massive fight. So, what we did is starting a (private) Wiki to write down *everything* about the game. And, thanks to concept-artists, supported with visuals this time. As you all know, pictures say more than a thousand words. Hence, my busy guys don’t even read thousand words.

Hmmm, not a very nice shot of that livingroom right? But remember how the Radar Station transformed from boring concrete hollow boxes to something nice!

Ok, last example. I saw this movie

got jalous, and restarted The Never Ending Story on realtime G.I. Everyone who has spend time on this knows G.I. is extremely difficult to get it done with compelling results at reasonable speed. So, weeks (and also the coming vacation weeks) will spend on the matter, but don’t expect any visible results soon. All in all, you can’t say I’m doing nothing. It’s just that I can’t take a cool snapshot to show you!

So… no “visible progress”? Not really no, sorry. However, we’re making another demo movie. Which is actually a short part of the game, and focuses more on horror again. I planned to release that movie somewhere this summer (and hopefully attract more help again), but as you may have understand from the text, probably it will be late autumn again ;) Better late than never!

All right, got to catch a train to Poland now…. That sounded a bit weird.

Thursday, May 31, 2012

Making of Radar demo #8: Morphing Animations

As promised, a Blog update about monster-animations without the usual delay. Ready for the European Football tournament btw? I'm ready, at least for drinking beer in the pub while the match is playing on a screen somewhere behind me. Let's hope Portugal, Germany or Denmark doesn't end my good excuse to visit the pub in the middle of the week abruptly.


Right. The "RadarBlob" monster wasn't supposed to be animated at first. Simple, lack of time. I still need to upgrade the entire skeleton-animation system. Support for other files (now it's only Milkshape...), additive blending, making good use of modern GPU techniques, ragdolls, et cetera. Another reason for skipping animation was the lack of a good animator. Which is also the reason I still haven't implemented a renewed system. First I want a human player or monster with good animations. Sorry, but I can't code blind or on "dummies", need real test-subjects!

But... while looking at the static, "frozen", monster, I wondered how the heck we could finish that demo movie a little bit spectacular. The model, textures and shading had been improved, but other than that it was as interesting as a vase. It would look even more ridiculous if the sound would be playing dangerous music, angry monster digesting sounds and steam blowers while nothing would really happen visually. No, we needed movement, even if it was something simple. But how to do that fast & easy? The answer: Morphing Animations.


Teenage Morphing hero Blobs
------------------------------
Morphing. It sounds like a technique the Power Rangers would use, but in 3D terminology it means as much as changing shape-A into shape-B. It's pretty simple, and as well an ancient technique. Quake1 already used morphing animations for its monsters and soldiers. How it works? Imagine a ball made of 100 vertices. New 3 seconds later, imagine the same sphere, but squeezed. The 100 vertices moved to another place in order to give a "squeezed" appearance to the same ball. The initial pose and the squeezed pose 3 seconds later can be called 2 "Keyframes". If we store those keyframes into the computer memory (thus storing all 100 vertex-positions per keyframe), we can interpolate the vertex positions between those 2 keyframes over the timeline. Useful, so we don't have to store hundreds or thousands of frames.
for each vertex
.....currentVertexPosition = lerp( frame1VertexPos, frame2VertexPos, frameDelta );
* frameDelta = a value between 0 and 1. 0.25 means we're at 25% towards frame2


The math is pretty simple, and also the file-formats are straight forward. Just store the vertex-positions (and normals) at certain keyframes. Another important note, Morphing animations are very flexible, making it suitable for organic abstract shapes like our RadarBlob. Unlike Skeleton animations where the vertices are bound to a bone, we can place the vertices everywhere we like. You can change a humanoid into the Hulk, or a cube. Just as long the vertex-count and their polygon-relation stays the same.

Yet Morphing animations aren't that common anymore. They have some serious issues. First, in the old Quake times, models were much simpler. A relative low vertex-count (a few hundred or so), and just a few, relative simple, animations. These days our monsters have much higher polycounts, and more + longer animations. The CPU would have to loop through much bigger vertexlists to interpolate all positions, and also the memory would get a hit to store it all. For example, our RadarBlob has ~8.000 vertices. In optimized form with indices, it has ~3.100. It would mean the CPU has to update 3100 vertices, for each monster, each frame. And storing a single keyframe would cost at least 3100 x 12(bytes) = 36 kb. In practice it doubles, as you may also want to store normals.


Why Skeletor is more powerful
------------------------------
It's not that a modern CPU wouldn't be able to deal with these numbers. Hey, don't forget the hardware also grew in numbers since the Quake era. Yet it feels wrong to do it this "brute force" way. And it is wrong, I'll show you how the GPU can help down below. But last but not least, another good reason why Skeleton animations took over are the static restrictions. You can calculate the vertex-positions at the fly, but more likely you'll read them from an animation file (like the good old MD2 files). The animations here are "fixed", you can't just alter specific body parts during the animation. For example, having the upper-body or head/eyes follow a dynamic target gets difficult. Ragdoll animations, which is based on fully dynamic behavior, calculated by collision volumes falling on the ground, are nearly impossible in combination with Morphing animations. You can use Verlet or Cloth physics to alter the vertex-positions, but it will make the character fall like a combination between pudding & a deflated sexdoll.

Skeleton animations do not store vertex positions or anything. Instead, it stores a "skeleton", a bunch of joints and their relations ("bones"). Vertices on their turn will be assigned to one or more bones. Your left hand for example would be assigned to the "Left-wrist" bone. Fingers on the same left hand are assigned to sub-bones. If the wrist rotates or moves, all sub-bones rotate and move along with it, and so will the assigned vertices do. Yes, in essence this still means we have to recalculate all vertex-positions individually by multiplying their positions with their host-bone matrices. But skeletons have three major strengths over Morphing:
1- You only have to store the joint-matrices(or quaternion’s) per keyframe. An average humanoid game-skeleton only has 30 to 50 joints or so. Saves a lot of RAM, and makes the files smaller.
2- You can dynamically alter a single, or multiple bones, and all child-bones + their vertices will nicely follow. Very useful for aiming, looking at, ragdoll physics, IK, or other dynamic behavior that can't be stored in pre-calculated animation files.
3- You can easily combine animations. The legs run while the upper-body shoots bazooka's, while the face talks shit.


Morphing, the Revival
------------------------------
Ok, we know now why we shouldn't use Morphing, but yet we did. Look, if you make use of modern techniques, Morphing can still be a faster solution than skeletons, it's easier to implement, and it still suits better with organic shapes. I mean, how the hell would you make a suitable skeleton for this abomination?
I tried, but no…

We didn't need bullet-Time Trinity animations, just a disgusting sack of hydraulic blubber breathing a bit. So, Morphing would be a fine choice sir, the waiter said. But how to get it a bit fast? First we would need to get rid of the CPU. I'm not a fan of moving *everything* to the GPU just to say "Got a 100% GPU solution here!", those Quad-cores need to move their lazy asses as well. But it's just a fact that GPU's are much faster when it comes to process big array that require vector math. Updating vertices on the CPU would be a disaster anyway, as it would prevent you from using Vertex-Buffer-Objects, unless you stream back the updated vertices each cycle. No go.

The VBO just contains the monster in its original pose. When we render it, the Vertex-Shader will do the position-interpolation math, instead of a CPU. The math is simple, just "lerp" the vertex between the current and the next-frame vertex-position, then proceed as usual.
 // Get the vertex positions for the current and next frame 
 float3 frame1Pos= tex2D( positionTex, frame1TX ).xyz;
 float3 frame2Pos= tex2D( positionTex, frame2TX ).xyz;
 // Interpolate
 float3 vPos = lerp( frame1Pos, frame2Pos, frameDelta );
 // Output
 out.vPos = mul( modelViewProjMatrix, float4( vPos, 1.f ) );
But... how does the Vertex-Shader know what the current and next frame positions are? Easy Does It, we use a texture. This (16 bit floating point) texture contains ALL vertex-positions for ALL keyframes. That's sounds like a whole lot, but don't forget a whole lot pixels fit in a 2D image. A single RGB pixel can hold a XYZ position (in local space), so do the math:
* RadarBlob: 3100 vertices
* 256 x 256 2D texture = 65.536 pixels
* 65.536 / 3100 = 21

In other words, a 256 x 256 image would be able to store 21 keyframes for this particular model. When using a 512x512 texture the number quadruples, and don't forget you could use a different image for each animation eventually. Anyway, the Vertex-Shader has to fetch 2 of those pixels for each vertex. You can fill the image anyway you want, but I just filled it the optimal way. Each vertex gets an unique ID, a number between 0 and 3100 in this RadarBlob-case. This ID is stored along with the vertex in the VBO. In my case I stored it in the Texture coordinate.z. So the texture-lookup index of a vertex could be calculated as follow:
uniform int   frameNumber. // Current keyFrame index (0..x)
uniform float frameDelta // Current position between current and next frame (0..1)  
 
// index = Frame offset  +  vertex offset within frame
// index = 3100 * frameNumber + vertexID
int frame1Index = modelVertexCount * frameNumber +  in.vertexTexcoord.z;
int frame2Index = modelVertexCount * (frameNumber+1) +  in.vertexTexcoord.z;

// Change the 1D lookup index to a 2D texture coordinate, for a 256 x 256 pixel image
float2 frame1TX = float2( frame1Index % 256, floor(frame1Index / 256) );
float2 frame2TX = float2( frame2Index % 256, floor(frame2Index / 256) );
 
// Add half a texel to access the center of a pixel in the texture.
// You also may want to turn of linear-filtering for the 256x256 texture btw
const float2 HALFTEX  = float2( 0.5f / 256.f, 0.5f / 256.f );
 frame1TX += HALFTEX;
 frame2TX += HALFTEX;
 
// Get the vertex positions for the current and next frame 
float3 frame1Pos= tex2D( positionTex, frame1TX ).xyz;
float3 frame2Pos= tex2D( positionTex, frame2TX ).xyz;

// Interpolate
float3 vPos = lerp( frame1Pos, frame2Pos, frameDelta );
// Eventually you can also lerp between the original pose if you like dynamic control
// on the animation "influence"
 vPos = lerp( in.originalVpos.xyz, vPos, animationInfluence );
 
// Output
 out.vPos = mul( modelViewProjMatrix, float4( vPos, 1.f ) );

That's pretty much it. Feed the Vertex-Shader a texture that contains all animated positions, and you're good to go. Uhmmmm... how to get those textures? I quickly made a little program that imports a sequence OBJ files. Then it would just loop through all vertices and store it in an array that would be suitable to build a OpenGL texture with later on:
for each OBJfile
.....for each vertex in OBJfile
..........array[index++] = vertex.xyz

Sounds easy, and it is pretty easy, yet I'll have to WARN about a few things:
* Make sure all OBJ files have the exact same vertex-count and order. If one file has a different storage, your animation will turn into a polygon massacre.
* In case you want to smooth / share vertices to make use of indices, do it before storing them into this texture. The numbering and order must match with the model VBO in your (game)app later on.
* Centrate the OBJ files in the same way you would do in your program, or you'll get an offset on all coordinates.


Whaaa, FLAT shading?!
------------------------------
If you try the code above, it seems to work nicely at a first glance, but take your magnifier and flashlight Sherlock. See that? The lighting on the models seems.... weird. The RadarBlob breaths, but the lighting doesn't seem to change along with the movement. No shit Sherlock, that's because you didn't alter the normals yet (unless you already got suspicious and added some more code ;))!

If you rotate a polygon, the normal has to rotate with it in order to keep the lighting results correct. Only problem is that you can't do this in a vertex-shader, unless you know all neighbor vertex-positions as well. That's possible, but it requires a lot more sampling and duplicate calculations just to get the normal correct. Good thing we have Geometry Shaders these days. Geometry Shaders are actually aware of the entire polygon, as it takes primitives for breakfast. In other words, you'll get the three (morphed) vertex-positions, so you can relative easily recalculate a normal and eventually the (bi)Tangents as well.


Problem solved? If you love FLAT shading, then yes. Otherwise, you prepare to get shocked. The lighting will be correct, but the smoothing seems to be entirely gone. What happened?! Congratz, you just screwed up the smoothing and found out how flat shading works. Making a smooth shade basically involved bending/averaging normals on polygons that share the same vertices.
Your Geometry Shader however just calculated the (correct!) normal for each single triangle. What it should do is smooth the normals with neighbor triangles but... again, that is not possible unless you store & pass additional data for each vertex. By default, a GS has no access to neighbor primitives.

The good old CPU morphing methods didn't just store the altered vertexpositions for each keyframe, it also stored the (bended) normals, and interpolated between them. So, why not just take the easy route and do this as well? Make a second texture that contains the normals, in the same fashion as we did with the vertex-positions. Oh, and don't forget to smooth the model already BEFORE you insert the normals into this texture! Then in the vertex-shader, also sample the 2(or 3) normals and interpolate them.
float3 frame1Nrm= tex2D( normalTex, frame1TX ).xyz;
float3 frame2Nrm= tex2D( normalTex, frame2TX ).xyz;
float3 vNrm = lerp( frame1Nrm, frame2Nrm, frameDelta );
.......vNrm = normalize( vNrm ); // don't forget. You naughty boy.

Big chance you're using normalMapping as well, so you will also need the tangents and maybe biTangents. You could either make some more textures, but if you are concerned about having so many textures, you can also give the Geometry-Shader a second chance. Now that the GS received smoothed normals, it will calculate smoothed (bi)Tangents as well:
TRIANGLE
TRIANGLE_OUT
void main(  AttribArray iPos  : POSITION,
                AttribArray iTexcoord  : TEXCOORD0,
                AttribArray iNormal  : TEXCOORD1 // Smoothed!
         )
{
 // Just some remapping, lazy code
 float3 vert[3];
  vert[0] = iPos[0];
  vert[1] = iPos[1];
  vert[2] = iPos[2];
 float3 nrm[3];
  nrm[0] = iNormal[0];
  nrm[1] = iNormal[1];
  nrm[2] = iNormal[2];
 float2 tx[3];
  tx[0] = iTexcoord[0].xy;
  tx[1] = iTexcoord[1].xy;
  tx[2] = iTexcoord[2].xy;
 float3  tangent[3];
 float3  biTang[3];
  
 for ( int i=0; i<3; i++)
 {
  /* SORT */
  if ( tx[0].y < tx[1].y )
  {
   float3  tmpV = vert[0];
    vert[0] = vert[1];
    vert[1] = tmpV;
   float2 tmpTX = tx[0];
    tx[0] = tx[1];
    tx[1] = tmpTX;
  }
  if ( tx[0].y < tx[2].y )
  {
   float3  tmpV = vert[0];
    vert[0] = vert[2];
    vert[2] = tmpV;
   float2 tmpTX = tx[0];
    tx[0] = tx[2];
    tx[2] = tmpTX;
  }
  if ( tx[1].y < tx[2].y )
  {
   float3  tmpV = vert[1];
    vert[1] = vert[2];
    vert[2] = tmpV;
   float2 tmpTX = tx[1];
    tx[1] = tx[2];
    tx[2] = tmpTX;
  }  
  
  /* CALCULATE TANGENT */
  float interp;
  if ( abs(tx[2].y - tx[0].y) < 0.0001f ) 
   interp = 1.f; else
   interp = (tx[1].y - tx[0].y) / (tx[2].y - tx[0].y);
   
  float3 vt  = lerp( vert[0], vert[2], interp );
   interp = tx[0].x + (tx[2].x - tx[0].x) * interp;
   vt     -= vert[1];
   
  if (tx[1].x < interp) vt *= -1.f;
  float dt = dot( vt, nrm[i] );
   vt     -= nrm[i] * dt;
   tangent[i] = normalize(vt);
     
   
  /* SORT */  
  if ( tx[0].x < tx[1].x )
  {
   float3  tmpV = vert[0];
    vert[0] = vert[1];
    vert[1] = tmpV;
   float2 tmpTX = tx[0];
    tx[0] = tx[1];
    tx[1] = tmpTX;
  }
  if ( tx[0].x < tx[2].x )
  {
   float3  tmpV = vert[0];
    vert[0] = vert[2];
    vert[2] = tmpV;
   float2 tmpTX = tx[0];
    tx[0] = tx[2];
    tx[2] = tmpTX;
  }
  if ( tx[1].x < tx[2].x )
  {
   float3  tmpV = vert[1];
    vert[1] = vert[2];
    vert[2] = tmpV;
   float2 tmpTX = tx[1];
    tx[1] = tx[2];
    tx[2] = tmpTX;
  }
    
  
  /* CALCULATE BI-TANGENT */
  if ( abs(tx[2].x - tx[0].x) < 0.0001f ) 
   interp = 1.f; else
   interp = (tx[1].x - tx[0].x) / (tx[2].x - tx[0].x);
   
   vt  = lerp( vert[0], vert[2], interp );
   interp = tx[0].y + (tx[2].y - tx[0].y) * interp;
   vt     -= vert[1];
   
  if (tx[1].y < interp) vt *= -1.f;
   dt = dot( vt, nrm[i] );
   vt     -= nrm[i] * dt;
   biTang[i] = normalize(vt);  
 } // for
 
 // Output triangle
 emitVertex( iPos[0] : POSITION,  iTexcoord[0] : TEXCOORD0, iNormal[0] : 
                    TEXCOORD1, tangent[0] : TEXCOORD2, biTang[0] : TEXCOORD3 );
 emitVertex( iPos[1] : POSITION,  iTexcoord[1] : TEXCOORD0, iNormal[1] : 
                    TEXCOORD1, tangent[1] : TEXCOORD2, biTang[1] : TEXCOORD3 );
 emitVertex( iPos[2] : POSITION,  iTexcoord[2] : TEXCOORD0, iNormal[2] : 
                    TEXCOORD1, tangent[2] : TEXCOORD2, biTang[2] : TEXCOORD3 );
} // GP_AnimMorphUpdate

Hard to notice, but another little animation was oil streaming down. Just a timed fade-in of an oil texture. To make it "stream", the fade-mask moved from up to down.

Final tricks
------------------------------
We just made a Morphing solution that uses modern techniques to optimize performance such as VBO's (allowing to keep all data stored on the GPU instead of transferring vertex-data each time), without bothering the CPU to do the interpolation math,

Two more tricks I'd like to explain is having an "influence factor", and updating data inside a VBO. Morphing animations just aren't flexible when it comes to dynamic controls. But there is at least one simple trick you can apply: "influence". In the demo movie, you'll see the RadarBlob breathing much faster and more intense at the last seconds. We didn't make multiple animations though. We just speeded up the animation-timer, and increased this mysterious "influence factor". Well, if you took a good look at the code you already saw how it works: you just do a second interpolation between the original vertex pose, and the animated pose.

Last but not least, don't forget you can actually store the updated positions/normals into a (second) VBO. In the case of Tower22, this monster will get rendered many times per cycle. Three shadowcasting lamps are on its head, so it will appear in their depthMaps. Also the water reflection and glossy wall reflections will need this monster. All in all, this guy may get rendered up to 12 times in a single frame. Now the interpolation math isn't that hard, but the recalculation of the tangents and all the texture applies concerned me a bit. So instead of re-doing all those steps for each pass, I update the monster VBO first, using Vertex-Streaming / Transform-Feedback. So first store the morphed vertex-positions/normals/tangents for the current time into a secundary VBO, then for all passes just apply the 2nd VBO so we don't have to calculate anything anymore. See the links below for some details about this technique:
http://tower22.blogspot.com/2011/08/golden-particle-shower.html

Case closed.

Thursday, May 24, 2012

Making of Radar demo #7: a little bit of koreander on top

Almost through. To conclude this "Making off", I'd like to cover how we made / animated the monster, finalized the rooms, and last but not least, how the sounds were done. But that's for the next post, as I still have to ask David how he did it. My audio-knowledge doesn't go much further than a FMOD implementation and MC Hammer :)

Pimp my Radar
------------------------
As we arrived in December, quite a lot of the textures and assets had been done by then. Yet, some rooms still felt empty, out of place, or just not right. Placing another concrete wallpaper or toying around with decals (those are transparent overlays such as the wall-dirt, cracks, cigarette butts or signs) can help a lot, and also simple light-flare sprites added a lot of swing. But even better was to grab Julio's hand and walk through each room for final adjustments.

So you made a bunch of rooms with fancy graphical tricks and quality textures. But what is the "message" or function of each room? As mentioned before, by nature a concrete bunker isn't the most exciting place. To make the (rather long) movie-fly-through somewhat interesting, each room needed at least one eye-catcher. For example, the otherwise boring tunnels were filled with green lamps and airvent "gasses". For each room, we took a few screenshots, and then Julio Photosouped them. Mainly the light-setup was enhanced (ambient light, contrasts, fog), and objects or decals were added. A hole in the left wall, some wires on the right wall, empty bottle on the table, poop on the ceiling fan, that kind of stuff.

Those "perfected" versions of the rooms then got back in the mailbox, and were used as a master-reference model. Basically my task was to tweak shaders, lights or the scene setup until it matched as close as possible with the reference image. And in some cases, those images caused some extra modeling/texture work for Sergi and Julio. Other floors, pipes, canisters, et cetera. Maybe not the fastest method to get things done, but all in all, the quality of the rooms got a serious boost. Below a short overview of what the Nanny did in the Radar household.
You know those TV programs where a bunch of guys (+ a woman standing in their way) making over your house?
The barracks: > Added junk, rusty beds, cold wind from the outside, light flares
The dressroom:> Wires with plastic sheets, large rusty ceiling fan
The stair: > Added some pipes, a lamp, and a canister
Central room > Snow and wind. Added particle clouds, a better skybox, red lamps.
Toilets > We actually hided that useless room with lightshafts :)
ControlRoom > Terminal, alarm, red lights
Lower central > Water, waterdrips, more lamps, a bit of snowdust clouds
Tunnels > Green lampflares, airvent "clouds", large trunks, rack
Monsterroom > Ice, particles, monster, nitro-tanks
Warehouse > Ceiling pipes, floor damage, wet floor pools, filled the racks


Call me "RadarBlob"
-----------------------
Another last-minute secret guest was our monster -his name is "RadarBlob" by the way, nice to meet you too-. Even with better looking rooms, the whole demo trip was still a bit dull. Originally I planned to show some physics instead. Throwing barrels from the stairs and into the water. But since there were too many physics issues for a good Bob Hope show, (at that time we were upgrading to a newer version of the Newton physics engine as well) something else had to draw the attention. Since Tower22 is a horror-game, why not do something with erh… monsters?

With the limited time, we had to keep the monster simple. No AI or complex scripted stuff, and neither animations (hence we don't even have a real animator yet). The room where the monster was placed was just a meaningless space so far. Filled with water... It would have been quite an anti-climax to end the movie in that room, so I made a drawing of a turd-like thing, connected with hydraulic hoses to the ceiling. Yeah, I love the monster & mechanics combi. Reminds me of Doom, Quake, and all the hydraulic systems we deal with at my work.
Uhmmm... luckily Robert quickly made a more impressive, muscular turd variant. So, while we were pimping the rooms, Robert made a high-poly model and first-version textures. The first in-game versions still looked a bit dull though. It needed to be bigger in order to become a bit scary, and thus a new room with a higher ceiling. Also the specular lighting required a lot of tweaks to make it more nasty and icky. Unfortunately there was no time to make an advanced skin lighting technique (on the wish list, for sure), so I just uses sharp specular highlights and a bit of “RIM” (wrap-around or “backlighting”) to fix it. Furthermore, Julio upgraded the textures and added some ice chunks as well to add some sense in the scene. Icy water next and nitro-tanks… Let’s unfreeze the beast during the last demo minute.
Still sucks.
Ah, have a Snickers, and there was Julio's master reference drawing. It's nice to be creative.

Maybe using some kind of animation wouldn't be bad either. Leaking oil streams, steam particles blowing out, and a "breath" animation to make it come alive. Only problem was/is that the skeleton-animation features haven't been updated in the engine yet, and we ran out of time. Asides, using bones for an organic blob like this probably wouldn't be the most handy way to animate it anyway. So instead, we went for good old "Morphing" animations.

In the next post, that will hopefully quickly follow for a change, I'll show some more in-depth details about how we did that.

Sunday, May 13, 2012

Loading... please wait

What the hell is wrong with computers, or wait, what the hell is wrong with software these days? You would expect that future computers can handle our typical tasks without a sweat, but that's not exactly the case. Are the rising hardware-specs fooling us, or does the software get slower each iteration? Here an emotional plea from someone who still gots bothered by sluggish, hanging, syrup computers.


Holy shit, Intel-Inside!
In 1998 -I'll pick a year that Windows started working a bit-, we were able to browse the internet –still an ‘innocent’ toy back then-, write an e-mail(what?!), print a Word(Perfect) document, manage the disk via Explorer, and even better, play Halflife. Of course, we also had charming blue-screens and it wasn't all that fast. Booting the computer took centuries, you couldn't open too many programs at the same time, and internet was as slow as the brown paste Robocop eats. But that was mainly due the cables and hyperslow modems, being interrupted by a malformed robot-voice of your mother if she tried to call at the same time.

I don't know the exact numbers, but in our house, I believe we had a Pentium 233 or 300 at that time. Single core of course. The average user probably thought “multi-threading” was another word for warpspeed in Startrek back then. Memory... 128 MB or something? There was a Soundblaster, a 4 or 8 Gb harddrive called "Bigfoot" to make it sound even more awesome, and a 15 inch monitor that could be used to fire holes in boats with a pirate cannon. A 16x speed (16!) CD-Rom drive. And a disk-drive, just in case you needed to fix Windows. And yes, I've seen my father doing that a few thousand times. Not sure whether that was really necessary, or he just liked screwing around with Windows and the BIOS. We never really had stabile computers, that’s for sure.

Videocards. These days, for me, the videocard is the most important instrument in a computer. But back then it was a piece of luxery, not really needed. I believe we had a Voodoo 'something' card. And I never understood how it would make games run faster or more beautiful. Don't blame me, 1998 was also the year I started programming (after some Q-Basic in 1997). Anyhow, “Software rendering”, which means the CPU did all the 3D work instead of a specialized piece of hardware, was common.
Tower22 has become kitchen-interior rendering software.

Holy shit, 4 Intels inside!
Anyway, compare those numbers with what we have now. At least two or four 2.000 to 3.000 mHz cores. In dumb-theory, that should be about 20 to 40 times faster than the Pentium 300. In reality, it might be even faster for very specific tasks that fully utilize parallel processing, since Intel and AMD spend a lot of magic in Multithreading, Hyperthreading, and whatsoever. RAM memory exploded from 128/256 MB to 4 gigs, or 8+ in case you have a 64-bit system. At least 16 times more memory to work with (+ faster chips/buslines). Harddrives? I remember removing "big files" of 1 megabyte or more once in a while to make space for a new 300 MB game. Now I still have to remove "big programs" once in a while to make space on the 300 Gb drives. And 300 Gb isn't that much really, people manage to stuff terabytes with games/videos/porn. For the info, 1 terabyte is enough to back-up 125x 8Gb disks, or capture 212 single-layer DVD's. Hence, old disks couldn't even store 1 DVD. Then again DVD didn't exist yet, instead we had ~700 MB CD-Roms. I won't compare CD-Rom reading speeds. Last time I used that thing was.... no idaa. USB and online file transfer took over. As we laughed at our fathers with their 8” floppies and LP’s, our kids will laugh at us Compact-Disc generation.

Last but not least, we have videocards these days. Big expensive ones. Videocards on themselves may have 1+ gig of memory (can be used to hold your game geometry and textures for example), and a hotdamn fast set of GPU's. Now I can clearly see the videocards doing their work when it comes to running games. Every 2 or 3 years, I'll buy a new card (or sooner in case it burned again due stuck fans). And a game like Tower22 often doubles or triples the framerate. Good job. As for you, just compare your PC game collections. 1998: Halflife, Sin, Carmageddon II versus 2010+: Crysis2, Battlefield, GTA V (almost!), ... Now as an old whiner I'm not saying all games are better these days, but if you can't see the (graphical) progress, you're as blind as a beaten-up mole.


Holy shit, nothing happens inside!
…Then WHY am I not seeing this progress in other software? When writing an e-mail, Windows Live mail often hangs for 10 or 20 seconds because it's doing... something. An e-mail! Just text! Nice to have 4Gb RAM on my 32-bit system, but ~50% is used by Windows and background trash (yes, I check the starting-up programs with msconfig). Why is a chatting program like Skype using 100 MB? Internet is shit too. On my comp, there are always 4 to 8 pages open in the background. Consuming hundreds of megabytes. And I'm not talking about Radioplayers, video-streamers or Flashgames. Just forums and stuff. Pfff, Flash Games. how is it possible a simple zombie-killer flashgame takes up almost 100% CPU? It's a fucking Flash game, not Battlefield 6000. The NES did a better job. Using Chrome here by the way, Internet Explorer is even worse. If I click the "e" icon, I want to Google something within the next 3 seconds. Not first wait half a minute. Each iteration of IExplorer seems to get worse, even though they threw away a lot of useless features only housewives who had followed an internet-course would use. Jesus Christ, we have Fiberglass here, and it still feels like pushing turds through a 8mm plastic pipe.

More to complain? Sure, how about booting up. No matter how many times I tell Adobe to get the fuck out, it still keeps coming with updates. Every time. Is Adobe Reader so crappy it really needs an update every day? Probably it just doesn't install its updates very well, and keeps asking. Talking about updates. What on Earth is Windows Vista doing? Even if my computer is shut off from the internet, it still manages to find "updates" sometimes. And of course that always happens if I need to turn off quickly, or unannounced in the middle of the night. The Toshiba Laptop battery-alarm suddenly starts screaming like a Russian nuclear bomb silo. What happened? Vista decided to restart the (closed) laptop suddenly, and of course dozens of opened text/image files weren't saved. Yes I'm probably doing something wrong, but explain that to your grandma. Auto-update ok, but you'll have to be retarded to make a feature work like that.
Toying around with blurry reflections and glossy specular highlights for materials like this linoleum floor last week.


Sometimes it feels as if computers are slowing down deliberately after 1 or 2 years. Back in the old days you would buy a TV or VCR, expecting it to work for at least 60 years so your grandchildren could inherit it in case cold-bad times would come. Nowadays, everything falls apart after a few years. Hey people have money enough, make sure they buy our shit on a regular base. Same with mobile devices. Apart from disintegrating after a year, they keep relative slow as well. I’m pretty damn sure an average phone or industrial handheld still can’t do the good old Pentium tricks like running Halflife (software render) on a 800x600 resolution while downloading "Intergalactic"(RIP MCA) with Napster at the same time. I know that has to do with fitting mini-sized chips in a small casket, but look at the numbers… An industrial handheld barcode scanner with Windows CE/Mobile for example often runs on an ARM 533 mHz processor, with 128 MB RAM. That should be faster than the good old Pentium in theory. In practice, it doesn’t even run a single (.NET) program at decent speed. And if it crashes, it just hangs instead of getting a cool blue-screen. What a rip-off!


Software: Culture of Greed
All in all, the same old tasks are just as slow as 14 years ago. Except that the devices aren’t that big anymore, and websites, explorers, Word editors or email programs have more features and a "slick" look now. And sure, computers are doing a lot more simultaneously these days, it’s not the hardware's fault. And in my case, the computer partially got slow due the huge amount of programs. Virus scanners, Dropbox, creative tools + their drivers, and about 20 different programming tools. Now Delphi is pretty nice and quiet, but others interfere with the system like a meddlesome aunt.

Yet, that shouldn't be a problem if all programs back of as long as I don't call them. But each of them dumps crap in the register, has invisible stuff going on, bothers with all kinds of extra functions, and acts like a spoiled princes claiming all computer resources. That might be the main problem; the programming philosophy. I can’t speak for all, but it seems designers lend on the “infinite” resources of nowadays computers. 4 Gigs of RAM, so reserving 100 Megabytes more just in case can't hurt right? The user probably likes our cool product to start-up automatically, and check for updates in the background. Processor speed? Who cares, dual cores mate. Again, all of this wouldn't be a problem, if there weren't many more programs trying to do the same simultaneously. You can't have 10 kings on one throne. Yep, having more resources makes lazy, and I speak from experience since I’m also familiar with the other side; a few megahertz microcontrollers with 1kb memory. Such systems force you to make smarter solutions, caring about each bit. While on a modern PC, you can turn a simple application into behemoth for the sake of “easy maintainable programming”.

Microsoft should know better with their Live and Internet Explorer products. I can’t really speak for Windows 7 yet, but Vista gave a wrong example as its programs were using too much memory and CPU cycles as well. Why does Live Mail work on web-based technologies anyway? It's asking for performance problems. Sure, it may give some more options in these modern cloud / social-media / device-synchronizing times. But in the end, I just want check or write a mail and don't give a crap about all those features unless I explicitly ask for it. Usually I'm using Notepad over Word, or the old PaintShop V over PaintShop XI. You know why? Because it starts in a second, rather than half a minute, including loads or prompts and questions. Software-designers should try to make things more simplistic again, don't you agree?

Ah, that's better.