Sunday, August 26, 2012

Reflective conspiracy theories

A small step for man, but a giant leap for mankind
Before moving on, let's zero-G for a moment for Neil Armstrong. First man on the moon (and hopefully not the last), died at the age of 82, 25 august 2012. If that was a real step on a real moon, Neil will reserve a well deserved page in the history books for a long, long time. Something we mankind as a whole should be proud of. Although we kill each other each day for various reasons, we should realize we all share this tiny globe. Zooming out puts things in perspective, and Neil literally took that perspective when having a view on our little planet while standing on another floating rock in this endless cosmos. It’s such a huge performance that it's hard to believe we really did it...

Moon-landing hoax? Who shall say. John F Kennedy, chemtrails, 9-11 inside job, Saddam & biological weapons, Area 51, New world order? Both the present and history are full of mysteries, and the more you think about it, the more questions arise. Things aren’t always what they seem. Having a Moon-landing sure came at a good timing with those crazy Russians trying to outperform USA as well. And it surprises me that modern space missions -50 years technology evolution since the sixties- seem so extremely vulnerable (control room being overexcited because the Curiosity drove a few centimeters on Mars ?!) that it puts the much more ambitious/dangerous Moon-landing in a weird contrast.

But before just following the naysayers... Being skeptic is a natural, psychological phenomenon. And not taking everything for granted the media says is healthy. But consider other huge achievements. Didn't we laugh at the brothers Wright? Would Napoleon even dare to dream about the awesome power of a nuclear bomb? Huge pyramids being built with manpower only? Even got a slight idea of how CERN works? Would you run with thousand other soldiers on Utah beach while German bunkers are mowing down everything that moves? Men can do crazy stuff when being pushed! But the bottom line is that you or me will never know what really happened, because we weren't there, nor do we have thorough, inside knowledge of the matter. All we do is picking sides based on arguments we like to believe. And for that reason, here an *easy-to-consume* series of the Mythbusters testing some infamous Moon-Landing conspiracy theories including the footprints (on dry "sand"?), impossible light & shadows (multiple projector lights?), and the waving flag (in vacuum?). So before copying others, get your facts right and check out this must-see:
Mythbusters & Moonlanding

Let me spoil one thing already. Something we graphics-programmers *should* know. Why is that astronaut climbing of the ladder not completely black due the shadow? Exactly, because the moon surface reflects light partially. A perfect example of indirect lighting, ambient-light, Global Illumination, or whatever you like to call it. Neil, rest in peace. And for future astronauts, don't forget to draw a giant middlefinger on the Moon/Mars so we have better evidence next time. Saves a lot of discussion.


Reflections
-------------------------------------
As mentioned above, shadows and light bounce off surfaces. Not just to confuse conspiracy thinkers with illuminated astronauts, also simply to make things visible. If not directly, then indirectly eventually. Reflections are an example of that, and take an important role in creating realistic computer graphics. Unfortunately, everything with the word "indirect" in it seems to be hard to accomplish, even on modern powerful GPU's. But it's not impossible. Duke Nukem 3D already had mirrors, so did Mario 64, and Farcry was one of the first games to have spectacular water (for the time) that both refracted and reflected light.

Well, a GPU doesn't really reflect/refract light-rays. Unless you are making graphics based on Raytracing, but the standard for games still is rasterization, combined with a lot of (fake) tricks to simulate realistic light physics. Reflections are one of those hard to simulate tricks. Not that the tricks so far are superhard to implement, but they all have limitations. Let's walk through the gallery of reflection effects and conclude with a relative new one: RLR (Realtime Local Reflections) I recently implemented for Tower22. If you already know the ups and downs of CubeMaps and Planar reflections, you can go there right away.


Planar reflections
One of the oldest, accurate, tricks are planar reflections. It “simply” works by rendering the scene(that needs to be reflected) again, but mirrored, The picture below has 2 “mirror planes”. The ultra realistic water effect for example renders everything above(!) the plane, flipped on the Y axis. That’s pretty much it, although its common to render this mirrored scene into a texture(render-target) first. Because with textures, we can do cool shader effects such as colorizing, distortions, Fresnel, and so on.

Planar reflections are accurate but have two major problems: performance impact & complex (curvy) surfaces. The performance hit is easy to explain; you’ll have to render the scene again for each plane. This is the reason why games usually only have a single mirror or water-plane. Ironically the increasing GPU power didn’t help either. Sure you can re-render a scene much faster these days, but don’t forget it also takes a lot more effects to do so. Redoing a deferred-rendering pipeline, SSAO, soft shadows, G.I., parallax mapping and all other effects for a secondary pass would be too much. If you look carefully at the water(pools) in the T22 Radar movie, you’ll notice the reflected scene being a bit different… uglier. This is because lot’s of effects are disabled while rendering the mirrored scene for planar reflections. Just simply diffuseMapping with a fixed set of lights.

The second problem are complex surfaces. The mirror-planes on the image above are flat. That’s good enough for a marble floor, and even for water with waves (due all the distortions and dynamics, you won’t quickly notice the error). But how to cover a reflective ball? A sphere has an infinite amount of normals (pieces of flat surface pointing in some direction). Ok, game-spheres have a limited amount of triangles, but still a 100 sided sphere would also require 100 planar planes = 100x reflecting the scene to make a correct reflection. To put it simple, it’s WAY too much work. That’s why you won’t see correct reflections on curvy surfaces.

Conspiracy people! Notice the reflected scene in the waterpool being a bit different than the actual scene?


CubeMaps
CubeMaps are the answer on the typical problems with planar reflections… sort of. The idea is to sample the environment from all directions, and store it in a texture. Compare it with snapping a panorama photo. It’s called a cubeMap because we take 6 snapshots and “fold” them into a cube. Now we can both reflect and refract light simply by calculating a vector and sample from that location in the cubeMap texture. The crappy sample below tries to show how a cubeMap is build and how it can be used. The right-bottom image represents the scene from topview, the eye is the camera, and the red line a mirror. So if the eye would look to that mirror, it creates the green vectors for sampling from the cubeMap. In this situation the house would be visible in the mirror.

• Paraboloid maps are a varation on cubeMaps that only require 2 snapshots to fold a sphere. PM’s are faster to update in realtime, but lack some quality and require the environment to be sufficient tessellated though.

Since cubeMaps sample the environment in 360 degrees, they can be used on complex objects as well. Cars, spheres, glass statues, chrome guns, and so on. Problem solved? Well, not really. First of all, cubeMaps are only accurate for 1 point in space. In this example, the environment was sampled around the red dot. Stuff located at the red dot will correctly reflect (or refract) the environment, but the further it moves away from the sample-point, the less accurate it gets. That means we should sample cubeMaps for each possible location? No, that would be overdone. The advantage of curvy surfaces is that it’s really hard to tell whether the reflection is physically correct for an average viewer.

But at the same time, you can’t use a single cubeMap for a large reflective waterplane, because you will notice the inaccuracy at some point. What games often do is letting the map-artists place cubeMap “probes” manually at key locations. At the center of each room for example, or at places you expect shiny objects. Then reflective objects would pick the most useful(nearby) cubeMap. In Halflife 2 you can see this happening. Take a good look at the scope-glass on your crossbow… you’ll see the reflection suddenly changing while walking. This is because the crossbow switches over to another cubeMap probe to sample from.
• Tower22 updates a cubeMap nearby the camera each cycle and uses it for many surfaces. This means pretty correct (& dynamic!) reflections for nearby objects. Distant surfaces will lead to visible artifacts sometimes though.

A cubeMap requires 6 snapshots, thus rendering the scene 6 times. This is quite a lot, so cubeMaps are usually pre-rendered. Since we don’t have the scene again from that point, cubeMaps provide a much faster solution than planar reflections. However, being not updated realtime, you won’t see changes in the environment either. Wondered why soldiers didn’t get reflected in some of the glass windows or waterpools in Crysis2? That’s why. All in all, cubeMaps are only useful for (smaller) local objects, and/or stuff that only vaguely reflects such as a wet brick wall or dusty wood floor.


Other methods?
I don’t know them all, but Crytek introduced an interesting side-quest on their LPV (Lighting Propagation Volume) technique. To accomplish indirect lighting, one of the things they do is creating a set of 3D textures that contain the reflected light fluxes globally. Asides from G.I., this can also be used to get glossy(blurry) reflections by ray-marching through those 3D textures. I sort of tried this technique (different approach, but also having a 3D texture with a global/blurry representation of the surroundings). And did it work? Well judge for yourself.


Personally, I found it too slow for practical usage, although I must say I only tried it on an aging computer so far. But the real problem was the maximum ray-length. Since 3D textures quickly grow to very memory consuming textures, their sizes are limited. That means they only cover a small part of the scene (surrounding the camera), and/or a very low quality representation in case the pixels cover relative large areas. In this picture above, each cell in the 3D texture covered 20^3 centimeter. Which is quite accurate (for glossy reflections), but since the texture is only 64x64x64 pixels, a ray cannot travel further than 64 x 20cm = 12,5 meters. In practice it was even less due performance issues and the camera being in the middle. Only a few meters. So the wall behind the camera would be too far away for the wall in the front to reflect. This was fixed by using a second 3D texture with larger cells. You can see the room pixels suddenly get bigger in the bottom-left buffer picture. However, raymarching through 2 textures makes it even slower, and the raylength is still limited. All in all, reflections by raymarching through a 3D texture are sort of accurate, but very expensive, and useful for very blurry stuff only. I also wonder if Crysis2 really used reflections via LPV in the end btw… guess not.


RLR (Realtime Local Reflections)
In case you expect super advanced stuff now, nah, got to disappoint you then. If you expect a magical potion that fixes all the typical Planar & CubeMap reflection problems, I got to disappoint you as well. Nevertheless, RLR is a useful technique to use additionally. It gives accurate reflections, at a surprisingly good performance, and implementing this (post)screen effect is pretty easy. And no need to re-render the scene.

How it works? Simple. Just render the scene as you always do, in HDR if you like. Also store the normal, depth or position of each pixel, but likely you already have such a buffer for other effects, certainly if you’re having a Deferred Rendering pipeline. Now it’s MC-Reflector time. Render a screen filling quad, and for each pixel, send out a ray depending on its normal and the eyeVector. Yep, we’re raymarching again, but in 2D space this time. Push the ray forwards until it intersects elsewhere in the image. This can be checked by comparing the camera-distance-to-pixel and camera-distance-to-ray. In other words, if the ray intersects or gets behind a pixel, we break the loop and sample at that point. Now we have the reflected color. Multiply it by the source pixel specularity to get a result. The code could look like this:
pixNormal = tex2D( deferredNormalTex, screenQuadUV );
pix3DPosition = tex2D( deferredPositionTex, screenQuadUV );

int  steps = 0;
float3 rayPos = pix3DPosition.xyz;  // Start position (in 3D world space)
float3 rayDir = reflect( pixNormal, eyeVector ); // Travel direction (in 3D)
bool collided = false;
float4 screenUV;

while ( steps++  <  MAX_STEPS    &&  !collided )
{
 // Move the ray
 rayPos += rayDir * STEP_SIZE;

 // Convert the 3D position to a 2D screen space position
 screenUV     = mul( glstate.matrix.mvp, float4( ray.xyz, 1.f) );
 screenUV    /= screenUV.w;
 screenUV.z  *= -1.f;
 screenUV.xy  = (screenUV  +1.f) * 0.5f;

 // Sample pixel depth at ray location
 float enviDepth = tex2D( deferredPositionTex,  screenUV.xy ).w;

 // Check if it hits
 collided = length( rayPos – cameraPos  ) > enviDepth + SMALLMARGIN;
}

// Sample at ray target
Float3 result = tex2D(  sceneHDRtex, screenUV );
The nice thing about RLR is that it works on any surface. The green spot gets reflected on the low table, but also on the closet door. Also notice the books being reflected a bit, and the floor, and the wall. No matter how complex the scene is, the load stays the same.

Perfect! But wait, there are a few catches. How many steps do we have to take, and wouldn’t all those texture-reads hurt the performance? Well, RLR does not come for free of course, but since rays take small steps and usually travel in parallel, it allows good catching on the GPU. Second, you can reduce the number of cycles quite drastically by:
A: Do this on a smaller buffer (half the screensize for example)
B: Do not send rays at all for non-reflective pixels (such as the sky or very diffuse materials)
C: Let the ray travel bigger distances after a while
Or instead of letting the ray travel x centimeters in 3D space, you could also calculate a 2D direction vector and travel 1 pixel each loop-cyclus. If your screen is 1200 x 800 pixels, the maximum distance a ray could possibly travel would be 1442 pixels. To complement, make good use of the power of love, I mean blur. A wood floor has a more glossy reflection than a glass plate. What I did is storing the original output texture, and a heavily blurred variant on it. The end result interpolates between the two textures based on the pixel “glossiness” value.
 pixSpecularity = tex2D( deferredTexSpecular, screenQuadUV );
 pixGloss = pixSpecularity.w;

float3 reflection = tex2D( reflectionTex, screenQuadUV );
float3 reflectionBlur = tex2D( reflectionTex2, screenQuadUV );
 endResult = lerp( reflection, reflectionBlur, pixGloss ) * pixSpecularity.rgb;
// use additive blending to add the end result on top of the previous rendering work
Of course, there are ways to jitter as well, use your imagination. However, the deadliest catch of them all, giving RLR a C+ score instead of A+, is the fact this screen-space effect can only gather reflections from stuff… being rendered on the screen. Imagine the wallpaper wall in the screenshot being reflective. It should reflect something behind the camera then. But since we never rendered that part, we can’t gather it either. In other words, pixels that face towards the camera, or to something else outside the screen boundaries, cannot get their reflections. That makes RLR useless for mirrors, although some women may prefer a RLR technology mirror. Also be careful with pixels around the screen edges. Your code should have a detection for this so you can (smoothly!) blend over to a black color (= no reflection).

As said, RLR is not a substitution for CubeMaps or Planar Reflection. Be a ninja and know your tools. Planar reflections for large mirrors / water. RLR for surfaces that only reflect at a steeper view angle, (pre-rendered?) cubeMaps for other cases.

Saturday, August 18, 2012

T22 Testament

Time flies when... getting older. A little special moment last week when we brought our our little girl to the elementary school for the first time. Little backpack strapped on her back, shy and carefully entering a new environment, inspecting the classroom a bit. Usually the moms are the softies, but this time I felt like Forest Gump dropping of his son at the bus as well. Probably mom and dad were more emotional than daughter herself. So sweet!


But what else did we do? Not a whole lot, since I had to visit England for work. But a week ago one of our guys -concept artist Pablo-, asked if I could write down some more about "game-mechanics". You know, how the game would play. How fast does our hero run? How to eliminate your opponents? How many hearts does his health-bar have? Does he have a health-bar at all? And, maybe more important, what will you be doing in this game anyway? Unless you have access to my head or tortured one of the team guys to extract information, likely you won't really know how Tower22 will be exactly played. It's a horror game, sure. But what kind of horror game? Killing zombie hordes with a fry pan like the addictive Left-4-Dead? Slowly exploring and puzzling through an infected mansion? Doing bondage & whipping like Castlevania? Or is it more like Luigi's Mansion?

Obviously, the horror genre splits up in several directions. Like Braindead, The Shining or Twilight(shivers) aren't the same things either. If you read the "Genre / Gameplay" or the T22 website, you do have an indication though. Tower22 won't be about killing things all the time. It's more focused on exploring an environment that gets stranger and stranger, solving puzzles, and trying to stay away from boogeymen. And as it comes to the looks, it will be a gritty semi-realistic "Soviet" style, mixed with a bizarre nightmarish/dreamy style. However, that still does not explain the deeper details or core features that should make this game "fun" or "scary" (the paradox about horror games is that they're often not fun at all in order to make them scary).

Each game attaches itself to several (new) features, trying to make a flagship of those. “Babes & Guns”, "Unbeaten 3D Graphics, using the Super FX chip!". "Customize your underpants", "Defeat enemies by combining magic spells with your turbo Vortex-Spin-Moves!". Although I didn't manage it for T22 yet, try to make a single phrase catchy slogan that described the best part of your game. Yes we can! Well, powertalk or not, in the end the fun-quality of a game depends on which rules or "mechanics" were chosen, and how well it was done. Brew the right concoction of game ingredients. 45% jump-force, some shotgun, a bit of doors with keys, et cetera. Combine that with a proper implementation, meaning your controls/game-world/design style/story exploits these ingredients wisely, and you have yourself a good game.


Easier said than done. As said, artists and audio composers need to catch the style that blends perfectly with the game theme. The programmers need to code the controls, physics, puzzles and A.I. like a well oiled machine. The map builders need to design the world in such a way it lends itself for the chosen gameplay features (whether that is jumping, gunning, running, racing, puzzling or whatever). If you could do it all yourself, you would do it right of course, as it's all in your head. But we all know we'll need extra people to realise a game project. How to make sure all of them are facing the right direction? Exactly, by giving clear instructions. And making a Game Document is one those help-tools.

Just writing an A4 with a global description of the game idea isn't enough by far. When it comes to fine-tuning, all details need to be provided. And that goes deeper than you may think. How fast is your player exactly? How does the stamina system exactly work? How long does it take before an enemy returns fire after seeing you? How much items can the player carry? Should the player be able to jump? And each feature needs to be weighed with care. Do not just throw in elements because some other cool game has it too. For example, only add the ability to roll up in a Morph Ball if it fits with the story, style, and if the environment provides plenty of puzzles that requires this feature. Otherwise it would feel like a dumb gimmick, out of place.

This will result in tons of text. And to make it worse, that text is likely going to change over time as elements need to be play-tested. Being able to do a Rambo ball-twister twirl might sound like a good idea at first, but after some testing it could still suck. Which requires parts to be rewritten / adjusted. As a machine programmer who writes manuals or guides occasionally as well, I know 2 things about documentation.
-----A: Writing them takes a lot of them, maintaining them even more.
-----B: Nobody really reads them.

Which brings me to C: documents -if there are any- are outdated, getting delayed. Documenting is a lost child, certainly in smaller companies/groups where the first priority lays on making the actual product. We all know we should write our stuff down, but... not now.


What we got cooking? A stove. Yet we have to make it a bit more dirty and old for the finishing ugly touch.


Wikipedia
This brings to Wikipedia. Wiki... That word always make me think about tropical juice with a package design containing monkeys swinging over pink crocodiles in a jungle. But I don't have to explain you what Wiki(pedia) really is. What is important, is that Wiki works. It contains a HUGE amount of information, it gets expanded, updated, refreshed and corrected every minute, and moreover, people read it. Not just professors with white moustaches smoking pipes, everyone does it.

Hmmm... wouldn't it be a good idea to use some Wiki power for your (game)documents then? Well, thanks to Brian here who pointed this out, I learned this is possible, and quite easily really! You can download "Wikimedia", the toolset that allows to install your own “Wiki” on a server computer (you can download Wamp for the additional components to setup an Apache + SQL server required by Wiki). Now if we think about Wiki, we think about a worldwide shared encyclopedia. But don’t forget you can set it up in a private network too, making it suitable for companies or turds like me who like to keep their game-document secret for now.


All right. But what exactly makes this better than any other random documentation system? Wiki, PDF or goddamn Cuneiform, the contents stay the same right? Well let me explain. But instead of taking a game as example, I’ll take a harvester-machine. Yep, I went to England last week to study a machine of our friends over there, in order to document the whole thing. Why? Well writing down stuff triggers you to learn the matter, as you do research while writing. And of course, it’s supposed to bring over knowledge to other engineers/programmers/service people some day. But as said before, writing this document involves several problems:
#1 It’s huge. As I can’t finish it in one or two days, there is a good chance a higher priority project will interrupt, leaving a half-finished(=useless) document.

#2 The machine will be changed / updated in the future. Having to do a revision is a lot of work though, as you’ll need to check the entire document for changes. This often leads to outdated or even faulty documents.

#3 Making 1 big document that reads comfortable, requires writing skills.

#4 I know the programming parts, but not specific details about which hydraulic valves were used, how a wheel steering sensor exactly works, or the electric schedules of the cabin. Need help from others, but they face the same problems and writing in the same document sucks. Having a pile of separated files sucks as well, unless well categorized.

#5 Do you really think a new programmer is going through all that stuff? Probably he will suggest to rewrite the system in his own way. So for who & why did you write that document? And even people want to read it, can they still find it 4 years later between the huge pile of other documents?


Plenty of good excuses you can use to convince your boss to keep you away from boring writing work. But sorry, Wiki eliminates all these problems more or less. Which is probably also the reason why it’s such a big success. First of all, instead of writing long chapters, you should try to write your system as separate small blocks. Don’t worry about the relation between those blocks yet. For example, for this machine I could write a specific page about the Joystick, how the Cruise Control exactly works, or the Dieselengine. Or to map it to games, a block about “Healthbar”, “Enemy 3”, or “Player biography”. There is no limit to the Wiki page length, but I’ll advise you to keep the pages short and to the point. One or 2 “screens” at max for example, and just pin down the facts and numbers rather than making a flowing story with “maybes” or “possiblys” that raises questions instead of answers.

This solves the “#5 reading” problem. Instead of having to scan large documents for useable text, the end-user now does a certain query. Want to know more about how the brakes work on this machine, or how the inventory should be implemented in your game? Search “Brakes” or “Inventory”, and go directly to a compact page. No bullshit, just useable info. Which also helps less experienced writers (problem #3) btw. Summing facts is easier than creating an informative, yet readable story.

As we know, Wiki allows linking. A page about Napoleon Bonaparte could refer to another page about Waterloo, or French Cheese. This allows to zoom in further and further. When I describe the machine software, it starts with an overview of main functions such as “Driving”, “Steering”, or “Engine”. Then each function gets its own page containing more detailed info. How it works, which sensors / actuators are involved, adjustable parameters, common problems (for a troubleshoot), et cetera. Then we can dive even further. A page that described the related source-code, or specific details about hydraulic valves being used on that particular system. Manufacturer, suppliers, maximum load, installation schemes, known problem, … In a game document, the description of a certain level could refer to characters, weapons, and other entities being used there.

Tying together the blocks allows to make a rich and informative system, yet remaining clear as the individual pages remain relative short; the reader decides how far he zooms in. Asides, it also solves some more of our typical problems. You can expand your Wiki step by step. A half finished document isn’t readable, probably neither available either as it still floats somewhere on the local hard-drive of the author. But you can already make use of a Wiki that only contains information on the top levels. A dead link simply brings the reader to a “to be written” page. Your Wiki page just gets an address like any other website, and can be seen by everyone (with access to your network) with a web-browser. This makes it easy to find, even years later, and hence, it even encourages you or other authors to fix the Wiki in case of a dead link or error. Maybe I don’t know crap about cooling fans, but if an engineer reads the document and bounces on faulty info or an unfilled page, he can quickly edit it. This makes the documentation more complete and easier up-to-date. Btw, in the case of Tower22, many of the Wiki pages also generate (concept)drawing tasks for the artists



Wiki works, and the internet proved that over the last 10 years. So if you are struggling with the documentation, feel like no one reads/checks or contributes your hard work, or getting tired of piles of files, Wiki might work for you. Whether you are writing about games, harvesters or your stamp collection.

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.