Sunday, October 16, 2011

Compressor, Part 2/2

What the hell we're we doing again? Oh yes, texture compression. In short, the main advantages are less storage space, less (video)memory space, faster loading/streaming, and if you're a lucky guy, a (little) performance boost cause less bandwidth is required. Reason enough to implement compressed texture formats... but how?

When you target OpenGL, you can encode pixelData into the DXT1, DXT3 or DXT5 format. So first (1.) encode, then (2.) store it in a file (a DDS for example), (3.) load the file later on, and finally (4.) send the (compressed) pixelData to the videocard. Sounds pretty complicated, but we have some nifty tools.

==========================================================
1. The Creation
==========================================================
Load a (raw) image, such as a bitmap or TGA file. Then encode it to a DXT format (or BC in case you target DirectX applications). So... we have to dig in compression algorithms now, right? Of course not. Don't reinvent the wheel, be lazy, and make good use of existing tools.

You can download an existing convertor tool or try to find a plugin for your favourite painting program. There are plugs for Photoshop, Paint Shop Pro, Gimp, Paint.NET... These plugins typically convert a common image format to a DDS file. You can skip step 1 and 2 of this tutorial now, peace of cake. Have a good look though. Not all convertors have equal quality and export options.

When my mobile research-lab was crunching on DDS, I had an old version of Paint Shop Pro though. Just ordered a new version (PSP X4), but no cool plugins at that time. I tried some other exporters, but they usually gave wrong output. Inverted RGB channels, flipped images, Lena changing into a guy, et cetera. Some claimed ATI has a good quality exporter, so I tried this instead: ATI Compress


Too bad, this is not a ready-to-use convertor, not even a command-line tool(I hate those, too lazy to type). It's a DLL you can include in your own programmed tools. Normally I would pass, but with the lack of good exporting tools so far, I gave it a try. And I got to say, it wasn't that hard at all (getting into C++ again took me more time). The ATI library is pretty straight forward. It has a function to compress raw image data, and some basic utilities to read/write DDS files.

1.- Load input image (bitmap, buttmap, tga, png, ...)
2.- Generate Mip-Maps (if you like)
3.- Let the ATI Compress library generate compressed pixelData (for each MipMap level)
4.- Store it as a DDS file (or your own custom format)

Mip-Maps ?!
In case you never heard of them, Mip-Maps are smaller ("blurred") variants of your texture. Pretty simple, half the size until you reach a 1x1 resolution. So a 256x256 image gets a 128, 64, 32, 16, 8, 4, 2 and 1 variant. But... why would you do that? Well, when looking a textured surface from a distance, one screen-pixel may have to sample from multiple texture-pixels. This can result in pixelated/blocky results, especially for textures with a high-frequency details or pattern such as black-white tiles. When you have mip-maps, the renderer will (automatically) pick a smaller, more blurry, variant to suppress this annoying artifact. A little downside is that mip-maps require extra image space (though the smaller resolution variants really don't take that much).

Sorry if you died from an epileptic attack.

OpenGL / DirectX have functions that generate mip-maps automatically for you. However, generating them takes time! So each time you load a texture that uses mip-mapping, you're wasting even more time with generating them. That's why some image formats (such as DDS) supports the storage of pre-fabricated mip-maps. So instead of rebuilding them each time again, you store smaller variants of the texture ready-to-use in the image file. In other words, it makes the loading times faster.

==========================================================
2. DDS File-Loader
==========================================================
Once your file has been generated somehow, you got to load it again in your app. I chose to use DDS files. Pretty obvious, cause this format supports compressed pixelData, storing prefab mip-maps, and even cubeMaps or layered (3D/Array) textures if you like. On top, it’s a common standard in Gameland nowadays. Monkeys see, monkeys do.

Luckily the DDS format is fairly easy. Mainly cause it doesn’t store its pixels in a wacky way. The array of pixels is stored exactly as OpenGL or DirectX expects it. This makes DDS fast to read, as you don’t have to swap bits or do other tricks before you load it to the GPU. It’s 1 on 1. But wait… D-D-S… stands for “Direct-Draw-Surace”… Isn’t that DirectX slang?? So we can’t use DDS in OpenGL apps?!

It is a DirectX thing indeed, and yep, you need a header file to get things working. But don’t worry. It’s not that your OpenGL program changes into a malformed Siamese twin with DirectX. Download the DirectX SDK, or if you are a Delphi user, you can use this: Clootie DX Pascal headers
Then include “DirectDraw.h / pas” in your program. Done.

// Delphi code.
function TEX_LoadFile_DDS( filename : string ) : TTexData;
var
ddsd :_DDSURFACEDESC2;
fileCode : array[0..3] of char;
factor : integer;
bufferSize : integer;
readBufferSize: integer;
pFile : THandle;
readBytes : Longword;
begin
{ Open file... Calling Powdered toast man }
pFile := CreateFile(PChar(filename), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if (pFile = INVALID_HANDLE_VALUE) then begin
showMessage( 'DDS Load Error: Cannot open file ' + filename );
Exit;
end;

{ Verify if it is a true DDS file. Not made-in-China fake stuff }
ReadFile( pFile, fileCode, 4, ReadBytes, nil);
if (fileCode[0] + fileCode[1] + fileCode[2] <> 'DDS') then begin
showMessage( 'DDS Load Error: file is not a valid DDS file.'#13+filename );
CloseHandle(pFile);
exit;
end;

{ Read surface descriptor.
A struct that tells what we can expect in this file. }
ReadFile( pFile, ddsd, sizeof(ddsd), ReadBytes, nil );

case ddsd.ddpfPixelFormat.dwFourCC of
FOURCC_DXT1 :
begin
// DXT1's compression ratio is 8:1
result.outputFormat := GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
result.isCompressed := True;
factor := 2;
end;
FOURCC_DXT3 :
begin
// DXT3's compression ratio is 4:1
result.outputFormat := GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
result.isCompressed := True;
factor := 4;
end;
FOURCC_DXT5 :
begin
// DXT5's compression ratio is 4:1
result.outputFormat := GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
result.isCompressed := True;
factor := 4;
end;
else begin
{ Not compressed. Oh shit, didn't implement that! }
result.isCompressed := False;
showMessage( 'DDS Load Error: Uncompressed format not supported!'+#13 + filename );
CloseHandle(pFile);
exit;
end;
end; // case ddsd.ddpfPixelFormat.dwFourCC


{ How big will the buffer need to be to load all of the pixel data
including mip-maps? }
if( ddsd.dwLinearSize = 0 ) then
begin
showMessage( 'DDS Load Error: dwLinearSize is 0!'+#13 + filename );
CloseHandle(pFile);
exit;
end;
if( ddsd.dwMipMapCount > 1 ) then
bufferSize := ddsd.dwLinearSize * factor else
bufferSize := ddsd.dwLinearSize;

{ Allocate pixel buffer, then read the (compressed)
PixelData (containing 1 or more MipMap levels) from the file }
readBufferSize := bufferSize * sizeof(char); // Calc buffer-size
GetMem( result.pixels, readBufferSize ); // Allocate memory
ReadFile( pFile, result.data^ , readBufferSize, ReadBytes, nil);
CloseHandle(pFile); // Close file

{ More output info }
result.width := ddsd.dwWidth;
result.height := ddsd.dwHeight;
result.numMipMaps := ddsd.dwMipMapCount;

{ Do we have a fourth Alpha channel doc? }
if( ddsd.ddpfPixelFormat.dwFourCC = FOURCC_DXT1 ) then
result.components := 3 else
result.components := 4;
end; // TEX_LoadFile_DDS


Just a shot. Playing around with ingame contrast here...

==========================================================
3. Pumping to the video-card
==========================================================
The final, and probably also most easiest step, is loading the (compressed) pixelData to the video-card. No worries, it’s pretty much the same as generating any other texture. Start with the daily stuff:

glEnable( GL_TEXTURE_2D );
glGenTextures( 1, @resultHandle );
glBindTexture( GL_TEXTURE_2D, resultHandle);
// Texture settings. Using mipmapping here...
glTexParameteri(GL_TEXTURE_2D,, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
glTexParameteri(GL_TEXTURE_2D,, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, );

Next we send the pixelData to the Twilight zone. One little thing to keep in mind is that we might have loaded multiple mipmaps, all in the same array of pixelData. So for each mipmap level, calculate the bytesize and offset in the array.

if textureData.usingCompression then begin
if textureData.outputFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT then
nBlockSize := 8 else
nBlockSize := 16;
{ Size of mipmap level 0 (original size) }
nHeight := textureData.height;
nWidth := textureData.width;
nOffset := 0;

{ Send the compressed mipmap(s) data to the texture }
for i:=0 to data.numMipMaps-1 do begin
if nWidth = 0 then nWidth := 1;
if nHeight = 0 then nHeight := 1;

nSize := ((nWidth+3) div 4) * ((nHeight+3)div 4) * nBlockSize;
glCompressedTexImage2DARB( GL_TEXTURE_2D,
i, //mipmap level
data.outputformat, // DXT1,3,5
nWidth,
nHeight,
0,
nSize,
pointer( integer(data.data) + nOffset)
);
nOffset := nOffset + nSize; // Offset in pixel buffer next time
// Half the image size for the next mip-map level...
nWidth := (nWidth div 2);
nHeight := (nHeight div 2);
end; // for i
end else ...

Texture quality
Last, here's a little Kung-fu trick. Probably you noticed the "Texture Quality" setting in most games. Chose between "Godlike, medium or fucked-up". Obviously, computers with lower-end hardware and/or limited video-memory should pick a lower setting. And you want this option too, don't you? Pretty easy. Just skip the first mipmap level(s) in the loop. This way OpenGL will only deal with smaller textures, as the higher level(s) get disposed again. That's all you need to know for now, Daniel San.

Saturday, October 8, 2011

Turbo marketing

No more calling home for Steve Jobs. I'm not really familiar with Apple products, but condolences to his beloved ones and many, many iFans. 56 is not an age to die, especially not if your head is still full of ideas and ambitions. Rest in peace Steve.



Pfew. The storm of emails and reactions is a bit over now. If you thought that demo movie was scary, I got my nerves in the throat as well last week! Having this unexpected, “massive” attention on the project is great free advertisement and can open doors, but is also scary at the same time. We hobby-developers, C++ and Turbo Pascal nerds may think T22 is sweet. But the common man who just wants to play a good game looks from a different perspective of course. It's either a cool product, or a piece of shit. If you buy a car, you don't care how much love was put into it, as long as it drives properly. In other words, T22 sort of got a little stress-test.

And... should I look for another hobby (such as whispering horses, playing flute, collecting Iranian stamps), or are we still standing? I suppose so :). Most of the reactions we're positive, a few hated it, and a couple found the second half of the demo movie an anti climax. Ugly HUD logo's, scripted shift!-run! (“QTE”) sequence, a goofy monster, and what in the devils name was that fat sprite doing at the end?

Taste differs of course. Especially when it comes to horror. I’m scared of clowns and porcelain puppets, others love them. Though some responders might have skipped the fact that this little demo-movie was done by a programmer without real art skills, in a 10% finished engine. Do you really want to know why the last part was scripted so much? Ok then... stair-climbing physics were still so bad that the player couldn't run up in a decent tempo. So I putted him on a rail, just like that goofy monster :D The available assets were very limited, which is why the weird robotic-hand comes from this test-model I made years ago in 5 minutes:

Third person?


Oh well, as long as the Angry Video Game Nerd doesn't say Tower22 is shitcrackers and he rather eats boiled apeballs, I guess we're ok. But sure, we still have a looong way to go. Rome wasn't made in one day either, especially not in the late night hours after a day of plumbing work! It's funny to see some think that we're actually almost done with a (sellable) Indie game. For example, I got mail from a website, asking if we could send a copy for review, as soon as the game is playable. I wish we can, but... do you have a minute?

As said before, we first need some more artists at least. The good news is that, just before T22 showed up on the internet, an extra person offered his help on the audio (when not busy with real work). Say hello to David Garcia Diaz(Espanol gringo):
http://davidgarciadiaz.com/



The whole thing got me a bit thinking about... the Power of Internet (oooh). The reason why I'm not shouting T22 of the roofs, is because I like to make sure I show something good. Friends and others sometimes ask me about showing it to publishers, sending it to website X, doing aggressive marketing, and so on. Ok, I’m not trying to beat CryEngine or UDK, but showing half baked garbage is like cutting yourself with a knife. Imagine Apple shows a cheap plastic, not-white-colored, monochrome, clunky prototype of the iPad6. Jobs would beat the hell out of the marketing team!

It definitely becomes clear that internet can be a jump platform that launches you sky-high. Think about young talented boys & girls that suddenly got famous via Youtube. Or the amount of clicks Half-life fan websites get every day. But the Internet can also be a deep pitfall. To show you, here some professor Dolittle statistics:

amount of views on this Blog on an average day: ~50
...(half from them are looking for an Albert Einstein picture, or stuff like Horseporn)
amount of views on the Blog on Friday 30 September: ~2.000
amount of Youtube views last 10 months, 1 week ago: ~2050
amount of Youtube views today: ~28.500

Enough ego tripping, but see what I mean? Because of some "advertisement", the numbers mega-quadripled. If, say 80%, of the viewers leave with a positive feeling about T22, we can be proud on ourselves. On the other hand, if 50% or more doesn't really like it or even hates it, you have a problem. Now Tower22 doesn't involve money, commercial stakes, and neither was it under development for many years already. But imagine your product, blood-sweat and tears, got burned because it leaked in an unfinished state, or just because the majority doesn't like it? I can imagine some developers must feel really, REALLY bad if their (life)work receives a lousy 5.0 on Gamespot, only 2 stars at IGN, or a Crocodile Dundee Turd award for the worst game of 2011.

The first blow is half the battle. Now we weren't prepared to fight actually, but all in all, we can breathe a sigh of relief. Reactions such as "Thanks, another set of underpants ruined", "Dont give up on this!", or people who like to buy this non-existing game are heartwarming. More than ever we have good reasons to keep developing. Cause there is a lot to improve! For one thing, it's time to have a website that explains things a bit better. Although it's really fun to see people speculating about the game;

- Demo1 was a programmer "art" movie with very limited assets
- I know, too much (motion) blur sucks
- Don't worry, I hate QTE too
- The game is far from finished. First trying to form a proper team
- The game is not in Russia. Sorry for the confusion. But yes, the setting is inspired on it.
- Yes, the game is all about the story, and I won't tell you. Hence, some of the team members don't even know the story! Top secret shit.
- The genre is a platform-survival-music game. Ok, survival horror then.
- It all takes place in a massive building. Though it’s not only dusty corridors and Soviet-IKEA apartments…
- No military, failed experiments or spooky hospitals in this game.
- Most the time, you won’t see monsters or other badguys. Slow suspence, getting winded up, claustrophobia and sound should do most of the terror.
- The player is not named Robert (unless we really can’t find a name. I didn’t name my own daughter yet either. Picking names is so damn difficult).
- Your character isn’t an action figure, yet he won’t be completely defenseless either
- A next (Tech) Demo is planned end this year
- Another movie that shows bits of the gameplay and boogiemen is planned for 2012
- A true release date indication? When it’s done!
- The game uses a homebrew engine programmed in classic Delphi7. It uses the libraries OpenGL 2x, Cg, FMOD, Python and Newton.


I like to finish this post with quotes that made me laugh, cry, vomit, or piss my pants. Next time we're back on Compression DDS files!

"This shit is trippy",
"Boner at 3:40"
"YOUR MOM is more scary than Tower22."
"He’s a plumber? Now it doesn’t suprise me that at the
.....destroyed apartment the only thing that didn’t collapse was the pipe.
>>"It’s all a cunning plan to increase his plumbing business by making you shit bricks."

"but the monster encounter and very last bit were more than a little ridiculous."
"I can't wait to shit my pants :)"
"You're in my world now? Batman...."
"I shitted my pants. Twice."
"What the FUCK did I just watch?!?
......And who's going to pay for my now-ruined chair?
"Note to self: chairs aren't good at holding huge amounts of shat bricks "
"If i was playing I would of dived the fuck out that window at the end, falling to your death is better than staying in that fucking haunted shit hole!"
"do you play as steve form minecraft? he looks very blocky"
>> "it's actually steve holt"

“fuck watching this again at 1am "just before bed"
“I have a fever, and the onlyprescription is more motion blur”

Friday, September 30, 2011

The plumber

Woke up, went to work, got myself some coffee, parked my ass on a chair, turned on the laptop, scratched my balls, checked the email... holy butcrack.

Wow. rockpapershotgun.com & IndieGames.com, a blog about, yep, Indy games, got notice of T22. Suddenly a lot more traffic on this crappy hole on the WWW, a dozen of Youtube abonnees + jokes, and some articles about T22 on these websites.

I'm shy by nature and hate to stand in the spotlights, but having this attention on your (life)work is great. Got to correct a few wrong assumptions though!

------------------------------------------------

...Skyscraper in the Soviet Union...

I mentioned the word "Soviet era style" several times. But... T22 is not really in the Soviet Union. The theme is certainly related, not only on the map design, but in the end the story has not much to do with Stalin & comrades.


...You play as Robert...

Thanks for the name suggestion! But honestly, Robert is a real-life person who is busy designing the player. The protagonist himself has no name yet! But I bet Robert is pleased!


...Then what the # is the game about?!...

Uh... It's hard to tell without spoiling things. The whole story and game is one big quest basically. All I can tell is that you are a caretaker doing jobs for the boss in a big (sort of Soviet style) skyscraper indeed.

And after a while, you do want your freedom (back). So the player, codename Robert, wants "to break free. God knows, God knows I want to break free." "I've Fallen in love"... wait, that's Queen. No love for Robert here!

And yep, the building is pretty much abondon. You'll try to puzzle/search your way out, which makes it a bit different than a zombie slasher or action game. But that doesn't mean you won't get your hands dirty eventually! Be prepared to be affraid, very affraid.


The demo movie is a bunch of scripted events btw. The game itself should give freedom. You decide where to go, when to go, and what to do if something happens. But hey, I wasn't that far programming ;)


...The sound hurts my ears / too much blur...

The sound, SSAO and motion blur are making havoc in this movie indeed. Partially because unfinished business, partially because of the cracky framerate. The movie was recorded on a somewhat older videocard (GeForce 8800) with FRAPS killing the CPU in the background. It made the sound go berserk, and the motion blur even nastier as the deltaTime between 2 frames was relative big.


...I'm a Plumber...

That would be pretty romantic right? Not sure if "a plumber by trademark" means I'm doing a proper job, or actually being a plumber? Too bad. The truth is, I can barely hold a baco. Never ever ask me to fix your toilet, unless you want a sinflood! In real life, I'm programming operating systems for pharmaceutical machines, warehouses, and my sweet 30 ton babies:
youtube1
youtube2


...Out soon...

Oh dear :) Don't want to spoil the party, but this game won't be out anywhere soon. Since we try to put the visual standard pretty high, and the T22 world is going to be kinda big, there is sh~tload of work to do. Programming the engine further, and having some maps, models, textures, sounds and animations would be nice too.

Do you remember the famous words "When it's done!". Well, that game is "done" all right. I'm going to say the same :) But seriously, the current target is forming a team, rather than creating the game right away. I can dream all I want, creating a "big" game with just a few hobbyists is not realistic.

So let's see if we can ensemble enough talented people to create a game in our spare time... Or at least make a good start, and then look further to get this baby on a more professional level. Doing this Blog and demo movies are part of the strategy; hopefully it attracts talented people!


That still sounds like a little boys dream, and... yes, maybe it is. So what? It doesn't mean it's impossible. The people we have here now are capable to create a game like this. The only problem is the lack of manpower so far. Let's show those bastards you don't need a 30-trillion budget to create a good game!



Ever thought about sending this pitch to a publisher?

Yes, but the project is still pretty premature. As said, a team too small for mass production, lot's to add to the engine (including fixing the motion blur! ). First things first, then we'll look further. At this point, I simply can't promise anything to an investor. Unless we work 400% on it maybe, but I don't think the other girls in this house would appreciate that :)


What to expect anywhere soon then?

* A second tech-Demo movie is targetted end this year. Not a "cinematic" horror movie like before, merely a showcase of the Radar Station map we use to test objects.
* A third horror-gameplay movie is targetted somewhere next year.
* A (simple) website end 2011 / begin 2012
* In the meanwhile, collecting more people. Currently we are looking for 3D environment mappers, environment concept-artists, possibly 1 more audio dude(tte), and a texture artist. In 2012 we'll be needing an animator as well.
* When the team is big enough and oiled, we'll start creating actual game content.


"Julio Iglesias is in charge of the concept art?.
You mean the singer?"

Yes.


What color of underpants do you wear?

Transparent-blue or with a panda print.


Halflife2 / Source MOD

No, it's not a Source MOD, neither using another engine such as UDK. it's all coded in-house. And Yes, quite some contents from the first demo movie are from HL2 indeed. Not that I wanted to, but how the hell is a plumber/programmer to create those textures and sounds then? Creating that monster (and animating it) required the maximum of my programmer-art skills. Got to start somewhere. Can't attract good people if I show stuff like this!

Excuses, got to play dirty sometimes. The next movie however will have our own textures and sounds though. In fact, pretty much most screenshots on the Blog from this year are using our own texture sets.


"This stupid video made me broke my Shift key"

Apologees, we'll send a new one.


...Amnesia / Penumbra...

T22 is quite often compared to Amnesia. And that's a good thing! They managed to put down a f#cking scary game with limited horsepower as well. Though it's not inspired on Amnesia. Never heard of the game until recently when one of the team members gave me a link. As a matter of fact, I don't know much horror games anyay. Only played a Doom3, a few Silent Hill's and Gamecube Resident Evils. And Amnesia made me poop my pants. Isn't that ironic?

The gamestyle is a bit similiar though. In Amnesia, instead of fighting, you run for a single enemy that wanders the area. A lot more terrifying if you ask me, although the ability to defend yourself once in a while would be nice...


... The fat lady at the end of that Demo movie, wtf?...

That was just a joke, putting that photo of my girlfriend there. No, Polish women aren't that fat :) Though this woman is as flat as a 2D sprite as well.

Thank you all for reading and your (positive) feedback. It makes it all worth! Back to work now!

Saturday, September 24, 2011

Compressor, Part 1/2

In case you are a programmer or texture-artist, you probably have heard about DDS files or texture compression. But if you are like me, you may have skipped all those articles. Pfff, compression, who needs that? Bitmaps and TGA files work for me, Pixel-data is pixel-data right? Besides, I've been taught that compression makes the quality worse, and reduces the performance because in the end, your pixels still have to be decompressed to a raw format. So what's the point?

Well forgive my ignorance. Guess I'm still traumatized because 12 years ago, I couldn't figure out why my sprites had jaggy pink edges when using JPEG files. Oh yes, the compression did that. But although the quality / performance arguments are valid, texture compression actually gives some nice possibilities. In this post, I'll write about using DXT compressed textures in your OpenGL program, and the DDS file format that can store this format.


1. For beginners: (de)compression
------------------------------------------------------------------------
For starters, as the name sais, compression is a technique to store (large) buffers of data with some tricks to reduce the size. When it comes to images, we usually have a big array of bytes. In a classic RGB (24 bit) image, each pixel takes 3 bytes. 8 bit for red, 8 bit for green, 8 bit for blue. Some images also have an 8-bit alpha channel, which makes the total size of a pixel 32 bit. Calculating the total buffer size is easy:
.....width * height * pixelSize. 512 x 512 x RGBA8(32 bit) = 1 MB

Cool, but 1 megabyte for a pretty small texture is huge (1 floppydisk!). Older photo camera’s would have their SD cards full after just a few clicks. So, that's why JPEG is often used. JPEG uses Huffman encoding, which is based on the probability a certain piece of data (pixelcolor) occurs. If we only have 20 different colors in an image, we can index the pixelcolors with a 5-bit (=32 possibilities) code. Further compression can be done by giving frequent colors a short bitcode, while rare colors get a longer code. Well, for a way better description, check this.

Smart huh? However, compressing the image has three main disadvantages. First there is usually quality loss. You probably have seen blurry blocks in JPEG images, especially when the color contrast is low. To put it simple, most compressed images NEVER reach the quality of a raw format (such as BMP or uncompressed TGA / PNG). Then again, if the resolution is big enough, compression settings are ok, and/or the small details don't really matter anyway, the loss is acceptable.

Second problem is the decompression-time. It simply takes some more time to convert the cryptic pixelmess to a raw format. Your video-card needs to produce raw (RGB 8-bit) pixeldata first, before the monitor can show it. Compare it to translating a Chinese movie to English. First a translator has to write down the English subtitles or do voice acting before it can be shown on TV. This process takes some time.

A third little problem is the compression itself. Just like decoding, encoding takes some extra effort as well. Luckily computers are fast these days, so you won't really notice. However... it's not fast enough to do many textures on the fly while rendering a game. This is why it usually happens "offline":

1.- Create your image (photograph / paint / capture raw data)
2.- Compress it in whatever file format
3.- Load in your application
4.- Decompress it back to raw-data
5.- Use (render) it.


Usually some quality loss is acceptable.


2. Compression & realtime Graphics
------------------------------------------------------------------------
So far, the only main advantage of using compressed images, is the reduced space on disk. You can't just load a JPEG and send it to the video-card texture memory right away. Nope, first you'll have to decode the data, then send a raw buffer of colors to the video-mem. So in the end you are still using the same amount of memory, it took extra time to decode, AND you lost quality. In other words, screw JPEG or any other compressed image format for graphics.

But wait. Things have changed a bit. Video-card memory has grown a lot last 10 years. From 32 MB to a gig or more. Unfortunately, games grow even faster. We want ultra-high res textures, and LOT's of them. Using all those textures at the same time requires quite a lot memory space, and bandwidth. Bandwidth? Imagine 10.000 hungry fat guys. You need 100 mcDonalds trucks to transport hamburgers. If all those trucks need to travel through a tunnel at the same time you get traffic-jams. Wouldn't it be nice if a single truck can carry more hamburgers, ending up with less trucks?


So, the graphic masters came up with compression algorithms specially designed for video-cards. I'm a newbie here as well, so I can't tell you the fine details, but you may have heard about DXT1, DXT3, DXT5, S3TC, BC1..7. Each of them is a compression method. Picking one is a trade-of between quality and space, and it also depends on what kind of image you want to compress (a normalMap, a simple blurry texture, a grayscale image, transparency yes/no). The compression ratio can be up to 1:6, which means a 1MB texture becomes ~170 kb.

The way the pixels are trashed together, is compatible with OpenGL / DirectX. That means you don't have to decompress the pixeldata first, before sending it to the videocard. No, you can send the packed buffer right away. That means the video-memory will be spared as well. Decompression happens on the fly by the hardware. I'm not sure if there is no performance penalty at all, but it seems the hardware can read compressed data just as fast as raw data. In fact...
you can even boost the performance! Remember the mcDonalds trucks? Since you need to transport less data on the buses, there will be less bandwidth issues as well. Now you probably won't notice this is you were only using a few textures anyway, but complex scenery such as a FPS game can benefit... Up to 20% according to some!

So far only 10 different textures are used in this snapshot. Or well, actually 20 as most objects also use a second or third image (normal/emissive/specular/height Map). Most textures have a resolution of 512x512 or 1024x1024, RGBA. So in total, there would be around (1024*1024 * 4(rgba) * 20(textures) = 80 MB of texture data pumped around every cycle (mip-maps, shadowMaps and deferred buffers not included). With compression, we can reduce this to ~20 MB.

Another cool detail is the loading time. Since you don’t need to convert stuff, and your harddisk or Blu-ray has to read less bytes, streaming goes faster. Who doesn’t like fast loading times? Tower22 streams maps and textures in the background while playing, so faster streaming is certainly nice.

Advantages
+ Less space required on disk / CD-Rom / Floppy disk / Blu-ray / Tape
+ Smaller files are loaded / streamed faster as well
+ Pre-build mipMaps in DDS files make the loading even faster.
+ Less space required in the video memory
+ Less bandwidth required. *Could* be a performance win.
+ Less quality maybe... but you can use bigger resolutions as well!
Disadvantages
- Quality loss. In some cases, compression is not worth it.
- Extra offline steps for the artists to produce compressed (DDS) files.

About the quality loss, this depends a bit. Matt(MJP) gave me some tips:

* Chose the proper compression methods
......- DXT1: Lower quality, higher compression, 1-bit alpha only(on/off)
......- DXT3: Better quality RGB, 4-bits for the alpha. Suitable for transparent ...... textures like foliage or a metal fence/grate.
......- DXT5: Suitable for images with smooth alpha channels or for normalMaps. Compress R and G, reconstruct B in shader.

* Use the right compression tool (nVidia, ATI, Microsoft, ...). Some do a better job than others, so carefully pick your weapons.

* You could pick a bigger resolution to compensate the quality loss, and still use less space in the end in some cases.

* Keep the option to use uncompressed textures, in case the quality sucks too much hairy balls.


Okidoki, but how in the name of SaintCrap can we make use of it? Consider three steps:
1.- Create a file with compressed image data... DDS files!
2.- Load the file in your program
3.- Create a (OpenGL/DirectX) texture using the compressed data

Next time, I'll tell you how to create DDS files, how to load them, and how to create an OpenGL texture using an (DXT) compressed image. Now it's time for beer.

Monday, September 12, 2011

Play on Player

Yea, my foot has been “restored”! Gypsum is gone, and now I can walk again (as if raped by a bull). Drink your milk boys & girls!


Movie-knowledge-check. A muscular robot? --> Arnold Schwarzenegger. That dude doing kicks and splits with a French accent; Jean Claude van Damme. The black man with that magical voice; Morgan Freeman of course. The simple guy telling his whole life story on a bus-stop bench; Tom Hanks. The psychopath shouting that Johny is here, Jack Nicholson. The teasing woman spreading her legs, Sharon Stone. "Can you fly bobby?", Kurtwood Smit. Roundhouse 360 kick; Chuck Norris.The little fatman with the big ###, uh, Ron Jeremy.

Just a grasp in the Hollywood Lucky Dip. And by now, the game scene also has an impressive repertoire of virtual actors. The jumping guy that looks like the earlier mentioned Ron; Super Mario. The medieval sadomachosism man with a whip; Simon Belmont. The fast blue hedgehog thing; Sonic. Hatatjapoerasturvat-something; Ruy from Streetfighter. "Your face, your ass, what's the difference?", Duke Nukem. The first polygonal breasted adventurer; Lara Croft. The chain-smoking sneaky grandpa; Solid Snake. That asswhipe stealing the princess every time; Bowser. The fairy-dude with the green hat; Link. Female bounty hunter; Samus Aran. The ninja with the skeleton head... Skorpion wins. The clumsy wannabe pirate; Guybrush Threepwood.

Now that my foot is ok, I can finally sport again. So here's a dressroom bench. It has been a while since I did a 3D object myself!

Not all games have strong characters with a complete biography, but creating a bond between game and player usually starts with putting down a loveable or interesting protagonist. A character being worth to pick up the joypad/keyboard. Cause, who wants to play a game with a stupid character anyway? Action hero's usually require a good look, a set of biceps and a doses of one-liners to make friends with the player. More serious games pass decorate the protagonist with a mysterious background. Lost your family, grew up in an underground sewer, shit like that. Who are you? Play the game and find out.

Yet other games manage to create a character that everybody instantly loves, such as Sackboy from Little Big Planet. Did you ever hear Mario talking by the way? We don’t even know where he lives exactly. Yet Mario is the most famous game-sprite in history. Some characters have that love-factor, others don’t. Now how about Tower22? What’s our plan to grab the player and drag him into the screen?

Here you go, a sketch of the player by Robert. There is still some cloth shopping and cheese-grater work to do here and there, but we’re getting somewhere. Not that Tower22 has much to do with “Communism” or “Russia”, but we chose the Soviet theme as a design-code. Therefore the character needs a typical Eastern Europe / Russian look as well. I’m not a fashion queen, but after a couple of visits in Eastern Europe, I can tell a few details. First, most men have a normal posture. No body building bullshit (who can afford the sport school), and neither fat. Most people work too hard to become fat. Second, a lot of men have short dark or blonde hair, often flat on the head (because they wore a cap or didn’t have time to smear 10 kg gel in it). A little bit the “army” look. Having a “tough-guy” attitude seems to be popular here by the way; lot’s of youth are wearing army trousers, trying to look dangerous and stuff.

Now our guy isn’t a kid or football hooligan anymore, he looks a bit exhausted. Yes, although things are slowly getting better in these regions, people still have sort of an depressed look if you ask me. Maybe it’s Slavic DNA, but I guess being bored, or just tired from all that work is playing part here as well. Read the lips: “Life isn’t easy”. Men like our player don’t have time (and money) to trim theirselves a cool George Cloney beard, buy the latest fashion shoes, and enjoy life. Fuck that, he wakes up to work. Nothing more, nothing less. Now that’s the kind of look we from T22 Next Top Model are looking for.

Robert made a whole set of (3D) "sketches" to pick from. We chose this one, because it has the tired "fuck-off", yet friendly, look. Now Robert is busy making a real 3D version. That version will be slightly different, and with little details such as beard, elder-marks, maybe a little scar, oil smear, sweat... In the meanwhile I have to make a realistic skin shader one day.

Not 100% sure, but most probably, the game will be using the first-person camera perspective. In other words, who knows how the player really looks like. Ok, you will see him in mirrors or in a few cut-scenes maybe, but most of the time you can just as well imagine playing the game with Robocop or Whoopy Goldberg... wait the player has white male arms. Never mind, you get the point. You won't see the player that much, the looks alone is not enough to make you care about the player.

So there goes the "lovely" factor. We need something else to get a love-match. A vast amount of cut-scenes with Reservoir Dogs dialogs maybe? Meeeh... not that I don't like those movies, but our player isn't exactly a joking piece of thug. And even if he was, T22 is a horror game remember. The game is supposed to make you poop your pants, not to piss yourself because it was so hilarious. Many horror-game/movie protagonists are normal, frightened, very human boys and girls. Would Resident Evil 1 still be scary if you run/jetpack through the corridors with Duke kicking ass? No, we want a fragile, sensitive, weak girl/guy. Like the Silent Hill or (older) Resident Evil characters... Though Chris took a steroid cure as well, his arms were 6 times bigger in the last RE game. But hey, RE5 wasn't scary either.

Heather from Silent Hill3, and Chris Redfield (without motor-oil injections) in the GC Remake version. Now Chris looks as if he can defend himself, but the difficult camera positions, stiff controls and scarce ammo still made him vulnerable for a bunch of stupid zombies. And for good reason, otherwise the game wouldn't be scary.

Although anti-hero, it's easier to identify with such characters in horrific settings. The player does the same what you would do: miss your gunshot and run like a girl. Well, probably you would also lock yourself on the toilet, rather than exploring a haunted zombie infested mansion. At least that's what I would do :) Either way, both you and the player are in the same nasty situation, so that makes a bond. And in case of a first-person-view, it's even easier to imagine that your own person is the player. Hence, likely T22 will be using the "Link" method. The what method? Yep, "Link", from Zelda. Or whatever his name is, because the player can always enter his own short name at the start of the game. This character keeps his mouth shut, has little to no emotions, and even a custom name.

In other words, your fantasy has to "complete" the character. Like with books. Some writers describe more details than others, but in the end your fantasy has to picture how the characters and scenery looks like. That's also why book-based-movies can disappoint. Shit, my hero didn't had a beard and brown hair! And that girl was a hot blonde, not a small Viking! Well, some people like to use their fantasy, others prefer to get everything served in ready-to-swallow chunks. But since the horror-genre is for a more select group anyway, I trust on your fantasy.

I'm not sure yet whether the (nameless) T22 player should talk or not. For one thing, there's not much company in that damn building anyway. But if the Boss gives a phone call, it would be silly to reply with silence. Other than that, our man is about 33 years old, normal functioning, and prefer to work with his hands. He's not a genius, neither dumb. An average, working-class (Russian) Joe, or should I say Dimitri or Jaroslaw? You didn't really plan to work in Tower22, but your hands were needed to take care of the building...

More barrels. Sergi is busy doing all kinds of IKEA object(sets). Boxes, barrels, beds, lamps, and so on. We need stuff to decorate that empty building with, right?

So let’s see… We have a non-hero, possibly without a name, that doesn't talk (much)... A prototype, normal human being. The type of guy who drops himself in the sofa with his stinky socks and a beer after work. Good to identify yourself with, but isn't that a bit... 'bland"? How about the mysterious background?!

Well, it would be stupid to spoil everything right here - right now, but let me say the player does have sort of a background. No, your parents weren't murdered. No, you didn't got raised in a spooky orphanage. No, you don't have CIA/KGB chips in your head. No, you didn't do ninja school. No, you don't suffer hallucinations after a mortar hit in Vietnam. No, you are not looking for your family. And no, you can't shit lightning-bolts from your arse either. So what the hell IS he? Play the game and find out :p

Saturday, September 3, 2011

Damn, still looking good!?


Wow! Doom is finally legalized in Germany! National Day! I guess most German gamers had their illegal copy on 5 floppy disks anyway, but those bans on violent games... sigh. You know what I think about games & violence:
Forbidding violent games?

But about Doom. If you tell the new generation of gamers about "id Software", then don't expect ringing alarm bells, twinkling enjoyed eyes, or hours of nostalgic talk. At its best, they might remember something about “Doom III”. In my opinion a very good game, but in the shadows(literally) of more innovative games of that time, such as Halflife2 and Farcry. Doom3 was well, 20 hours of shitting your pants & brainless shooting in darkness. Good enough for me, but not a shocking new formula.


New cars versus Grandpa’s unbreakable steam-tractor
Maybe they also noticed all the fuzz about that game "Duke Nukem Forever", which made the old boys nervous the last 15 years, but turned out to be a piece of . Conclusion of the new generation: we old bastards got stuck in history with Duke and Boom, or whatever that game was called. No doubt it was fun back then, but it’s time to move on. We old bastards on the other hand keep telling that games are shit these days. Like grandpa claiming his old steam-tractor is still superior to those modern machines equipped with electronics that nobody understands.

Nostalgia is a strong thing. Mark my words, you new generation wannabe-gamers (2000..anno now) will be complaining in 10 years as well. Telling everyone Call of Duty: Modern Warfare was way better than all those too-easy-4-hour-crap-virtual-3D-iMotion games we may meet in the future. As usual, everything was better in the good old days. Ask Alexander The Great, and he will confirm.

Nintendo & Wii tries to tickle the Nostalgia, using a different marketing strategy: Good old fun for the whole family (including labrador)... Too bad that they can't(don't want) get rid of their kiddy status. Asides from Nintendo's own series, most of the Wii games are weak excuses to wrap shitty stuff without immersion in a game-package, relying on the overrated Nunchuck. Simple, uncomplicated fun? Maybe, but not enough to hook this old gamer.

OT, Sergi made a sink... Don't know what to say more about sinks, but we need them.

Less serious, more fun
Now, who is right? Is nostalgia blinding us, or do we really have a point when complaining? All right, some nuance first. Doom was made in an era where good-looking quality games were scarce. Hence, it was one of the first "3D" games! Duke was the first game with boobs, humor and cities to explore instead of boring stone corridors. So titles like these would quickly rise above the average, had little to no competition, and got declared holy by the game-popes.

Yet, I dare to say games like Super Mario, Doom(1 / 2) or Duke Nukem still have a better thought-through design than many modern games. Whereas new games are taking themselves (too) serious with photo-realistic graphics and dramatic, cinematic gameplay, old games were more focusing on simple, yet challenging and very addictive mechanics. I finished "Double Dragon (SNES)" with my little brother about 5 million times, while I hardly finish new games these days anymore. At some point, I just lose interest. Even with quality titles such as GTA or Metal Gear Solid. Of course, that also has to do with my age, busy schedule, and being spoiled with too many good games last 18 years already. Chocolate cake doesn’t taste that special anymore after eating it six thousand times.

But when I'm in for a quick game, I usually start Doom or Red Alert, rather than newer titles. How come? Old rusty habits, or are these games really more fun? Both, I think. My major problems with nowadays games:

- It takes a while to get in the mood (complex story, slow build-up, learning all controls, ...). Not good if you don't have many hours of free time.
- But once used to it, these games are often (way) too easy.
- Not worth a second run. Once finished, they dissapear in the (virtual) cabinet.

Point 3 is typical for modern games. Their graphics, advanced scenery, teasers, and immersion usually keep you interested till the end. But the core-elements such as blasting foes or jumping platforms just isn't that much fun. Take GTA for example. Everyone loves the dialogs and exploring the city. But playing it all over again... Racing isn't that much of a challenge, neither are the simple shoot-outs where the computers does 95% of the aiming and cover for you. So what's left, are the dialogs and scenes you have already seen.

A game like Doom on the other hand brings you straight down to the action, 15 seconds after double-clicking \doom.exe. After 50 runs the AI and level-structure isn't really surprising either of course, but you can increase the difficulty to insane heights, and more important, firing the double barreled shotgun at an imp from nearby keeps satisfying, forever. These games are simple, yet brilliant and diverse at the same time.

A simple explanation for their good design might be the available time they got to tweak the levels and weapons. Now lot’s and lot’s of time is spend on making the maps and objects look good in the first place. High poly characters, huge libraries of textures, polishing the lighting, and so on. Making content for older games was simpler, so there was more time to test the maps. Where to put ammo, when to give a health bonus, where to place baddies. And if it sucked, maps or monsters were easy to scrap and replace.

More sinks! Btw, making this model + normalMap + specularMap takes more time than making a low-res sprite of a sink or toilet. Therefore it's harder to replace content, in case it doesn't really fit in the game.
----------------------------------------------------------------
Duke Legacy
I guess this is where it went wrong with the new Duke Nukem Forever… Too much struggle on making the content, too little testing, too much sweat/ego to scrap and redo things… As an old rusty gamer, I was a bit sad about the new Duke not being “Hail to the King baby”. DNF isn’t a bad game, and neither did I expect it to live up the hype. But it didn’t bring back old well-oiled shooter fun, and it certainly did not convince the new gamer generation. A mediocre product, nowhere near the old Duke achievement in 1996.

I already had sort of a bad feeling about it when seeing the few demo movies that were released throughout the years. Duke was struck by an identity crisis. Should he try to be an innovative, fresh game with modern elements such as sniping, driving vehicles and easy-gameplay (plenty of auto-saves, linear levels, lot's of hints, not too much enemies). Or should he stay with his core-business: shooting everything that moves & saving babes up tempo?

I wasn't there at the development, but it seems the creators got stuck somewhere between. Resulting in a game that is neither an oldskool-hardcore shooter, and neither a refreshing new game with superb graphics. It's frustrating difficult at some points, and too easy at the same time. It’s not long, nor short. It's a lot of firepower, but only carrying 2 guns and no mighty-boot at the same time. It's Duke humor but being-a-pussy-getting-killed-by-just-a-few-bullets at the same time. The enemies don't overwhelm you by intelligence, neither with big swarms as they did in the past. The pace was not slow & stealth, neither on steriods. The levels try to look good, but forgot the secrets, humor, freedom and fun that make you want to get the max out of them.

Vehicles or moving stuff doesn't surprise anyone anymore. But back then, this "metro" was a (also technological) highlight!

As said, it's not a bad game. But the new generation that compares it to Crysis or Deus-Ex will be disappointed by the many shortcomings; the game excels in nothing, and Duke’s silly poop-jokes won’t fix that either. Then, we older games get disappointed by the lack of challenge, not killing 100 pigs per minute, and boring level design. Yes, it surprised me that most of the scenes you have seen in 10-year old demo-movies, such as the casino, hoover dam, and cowboy stuff are still in the game. You can't tell me that it took fourteen years to finish those (few) levels... The problem was likely something else: it missed the simple yet addictive and aggressive gameplay that made the 1996 release so brilliant.

I think 3D Realms realized this very well in a pretty early stage. The fun isn't just there when firing a rocket at a bunch of aliens flying with a jetpack. But instead of having Duke-balls of steel and starting over from scratch, they grasped with the ideas & content they made so far, and tried to improve what they got. But probably this was a mission-impossible. Having spend so much blood, sweat and tears in their product, 3D Realms probably didn't want to scrap and disappoint their fans. But at the same time, they might have been too ashamed/unsure to release the game in its current shape. That's where 2K-Games interfered, by putting Gearbox on the Duke. Not to make it a better game, but just to make it sellable, finally. I understand their choice, yet it's a pity to witness the downfall of our old hero.

Roots, bloody roots
I’m just speculating of course, but it seems they took a few fundamental wrong decisions. Once they got behind schedule, being surpassed by better engines and other innovative games, they probably had to adjust their selling points as well. Making a copy of ’96 Duke 3D with improved graphics wouldn’t be enough. At least, not according to publishers that want to sell the game to a wide audience. Times of nonstop brainless shooting, 30 + 2 secret levels, and hard difficulty settings were over. Who to please? The old loyal fans, or the new generation of gamers? Probably they tried to please both, and that’s exactly what made the game fail I think.

In my humble opinion, Duke should have been more like its predecessor. That sounds lazy, but trying to be new and better is near to impossible these days, especially in the shooter genre. Duke wasn't going to steal the hearts of new gamers anyway, there are simply too much players out there now. (Virtual) heroes are just as easily forgotten as they rise these days. So why not going back to the roots, making a decent shooter game. Fast, aggressive humorous action, heavy weapons, whole armies of foes to shoot. A big bunch of fun-levels, not bound to realistic rules or a complex story. And a difficulty setting to separate the men from the boys.

For 2011 standards, that would actually make quite an original game. Hell, I dare to say it would even be fun with 2.5D (but High Quality) sprite graphics. Damn, that would look good. Or least original. Maybe the newer gamers wouldn't be interested... then again, Retro 2D Mario sells again, and I'm pretty sure there are plenty of old grumpy guys that haven't played a good old shooter since Halflife1, in their experience.

Little teaser for Demo2...

----------------------------------------------------------------
Ok professor, how about Tower22?
What design rules would Tower22 follow? Well, neither of them. Horror games are a complete different genre. The target is to give you just a single-ride, with complex & difficult gameplay. But a ride you will never forget because it was so goddamn strange/weird/unique/scary. Like Silent Hill or the older Resident Evil games did. However... I would love to make a 2.5D Duke Nukem, Command & Conquer, or beat 'm up like Double Dragon!

Talking about games, do you have a top10 (old or new, doesn't matter)? In random order:

0- Super Metroid (SNES)
1- Crusader: No Remorse (PC)
2- Doom2 (PC)
3- Halflife (PC)
4- Goldeneye (N64)
5- Zelda (SNES, N64, Majora's mask in particular)
6- Resident Evil Remake (GC)
7- C&C: Red Alert (PC)
8- GTA: San Andreas (PS2)
9- Red Dead Redemption (PS3, hey, that's a new game!)
10- Super Mario (Bros 3, World, 64... and I likes the Wii ones as well)

My top 10... counting from 0 ;)

Sunday, August 28, 2011

Golden particle shower

Let’s discuss some graphical tricks again. You may have seen ice patches in the screenshots from previous posts, but it still looks kinda odd, don’t you think. Is there something wrong with the ice shader, or is it just… What would you think if you if your steaming hot bathtub was half-frozen at the same time? We graphic programmers sometimes forget that effects can’t be tested on realism individually. It’s the whole picture that convinces or not.

In this case, the environment has to look freezing cold. Otherwise the water wouldn’t freeze right? A few tricks you can use for that:

- Use a grayscaled / blueish screen filter. Blue looks cold.
- Use blueish or gray-white fog
- Put snow / ice on all surfaces, not just a few pieces of ice on the water
- Make windy snowdust particles (nearby air-vents and such)
- Let is snow, let it snow, let it snow


Still got to learn those little fuckers not to fall through the ceiling. Maybe the depth-texture (from the player point of view) may help...

Since the summer here was one big fiasco (Global Freezing), I’m already in a Christmas mood. So I decided to start with some snow. But as usual, it required a whole lot more to implement a solid basis to make such effects. What we needed was a particle generator (and an editor to define them).

Now Engine22 already had a few techniques, but not flexible enough for Micheal Jackson moves, and certainly not fast enough to spray massive amounts of particles. And when it comes to particles, density does matter. Usually 5.000 smaller dots make a better volumetric shape than 5.00 somewhat bigger dots. Time for a revision on the old, CPU-based, particle code.


For starters, particles is nothing more than a “cloud” of (small) sprites that move around in a certain way. Simple examples are bloodsprays or flying debris after bullet impacts. But it’s also useful for complex volumetric shapes such as fire, smoke, gas, clouds or a water fountain. The power of particles is the simplicity to draw them, which allows to render large numbers that form a shape together. A single particle looks like shit, but as with ants, killer bees or football hooligans, the group dynamics make it a strong whole.

A particle can be a simple dot, or a textured billboard sprite. The simpler, the faster of course. But you can also apply lighting & shadowMapping on your particles to create cool effects such as lightshafts. Or let it bend / blur the background to create a heat haze for example. Same stuff as usual. More difficult is to render it in insane quantities, and to update particle positions in a realistic way. How smoke moves through the air? Well, I can’t tell you really. But at least I can share some methods to render large numbers of particles.

Smoke test - You'd better not try to model that in real 3D... And a single animated 2D sprite won't do the trick neither anno 2011...

Transform-Feedback (Vertex Streaming)
The simple way of doing particles is creating a big array of particle-structs. Let the CPU loop through the array, update the position with gravity or whatever forces, then render it as a sprite. Not bad, but your CPU will cripple when doing really large numbers (ten thousands). The GPU on the other hand… Wouldn’t it be nice to benefit from the GPU math skills and having all vertex data loaded on the GPU already, rather than passing thousands of coordinates? Think in magnitudes of hundred-thousands of particles, rather than thousands. Well, in theory that is. Having a lot of layers of transparent quads filling the screen can still cause fill-rate issues.

Maybe you know how to pass a VBO with vertex data to the GPU, but how to update the particle positions and store them back in a VBO without needing the CPU? Transform-Feedback is the magic OpenGL word. You don’t need that freaking CPU, neither clumsy textures to store data in pixels.

0. Create a VBO with vertex-data (positions, maybe texcoords/colors, or force vectors in case of particles).

1. Make a Vertex-Shader that updates the vertex data (positions, forces)
2. Store the Vertex-Shader output directly back into a second VBO (= Transform Feedback)
3. Render your particles (or cloth, or skinned character, or anything else) with the second VBO as input. Eventually use a geometry-shader to make billboards out of single vertices.
4. Next cycle, use the second VBO as input in step 1 and store results in the first VBO. Toggle for each cycle.


Dance dammit
So, as for particles, you can create a VBO that contains the maximum amount of particles. In case you can spawn up to 10.000 particles, then create a VBO with 10.000 points. Since geometry shaders can produce sprites out of a single vertex-position, you don’t need to store all 4 corner coordinates in that VBO. Asides positions, you probably need some more info to store per point. For example:

TVBO_Particle = packed record
......Position : TVector4f; // XYZ, W=scale
......Force : TVector4f; // Current velocity / force vector, W=lifetime
......Color : TVector3f; // Color modulator
......LookupCoords : TVector4f; // Pick a sub-texture from a bigger atlas texture
......Randoms : TVector4f; // Some more random numbers to vary data
End;

When creating the VBO, you only have to fill the static data; properties that won’t change such as the color, size lookup coordinates and random numbers. The dynamic properties such as position, lifetime and force will be updated in the Vertex-Shader that updates the VBO each cycle. A very simple approach could be:


OUT.Force.xyz = IN.Force.xyz + Gravity.xyz * cycleDeltaTime;
OUT.Force.a = IN.Force.a - cycleDeltaTime; // Decrease lifetime
OUT.Position.xyz = IN.Position.xyz + Force.xyz; // Update position


Go Recycle
Right, this will make your vertex fall down. At some point, it hits the ground or it should simply vanish after X seconds. Then what? You can’t create new vertices in a VBO… But you can recycle them of course. Notice I used “force.a” as a lifetime value:

If ( ( OUT.Force.a < 0.f ) || (OUT.Position.y < floor.y))
{
......// Particle ran out of time, or hit the ground
......// Respawn it (eventually with a delay)
......OUT.Force.a = maxParticleLifeTime * randomFactor;
......OUT.Force.xyz = initialParticleForce;
......OUT.Position.xyz = initialParticlePosition.xyz;
}

It will start over again next cycle. Probably you want to vary the initial properties a bit to prevent all particles starting at exactly the same point, with the same forces. Use some shader-math, input parameters, or like me, use a lookup texture. Depending on the overall time, you can pick from a texture that tells where to place it, what force to use, what color to use, and so on.

tx.x = elapsedTime / totalGeneratorLifeTime;
OUT.Position.xyz = generatorCenter.xyz + tex2D( dataTexture, tx );

You can also use such textures to morph the color over the time, or to fade them out after a while. Whatever you like Mac. In case of complex movement such as dancing Plutonium molecules, or a tornado, you can eventually encode an entire movement pattern in a 2D or 3D lookup texture. Use your creativity!

I still lack textures and finished shaders to show some cooler effects, but you can also use particles for tornados, rain, lava, flies circling around a turd, slime dripping from leaking pipes, electicity sparks, water splashes, fire, weather effects, plasma generators, exhaust pipes, and so on.


Make it quads please
For simplicity sake and to reduce the VBO size with 75%, we only store 1 vertex struct per particle. That means you can’t just render the damn thing. That’s where geometry shaders (finally) become useful. Given the camera matrix, particle position, and particle size, you can let it make billboards that always face the camera. Here some code:

POINT TRIANGLE_OUT
void main( AttribArray iPos : POSITION,
uniform float3 camPos , // camera position
) {
// Make quad-sprites from points
float4 p1,p2,p3,p4;
float3 particleCenterPos = iPos[0].xyz;
float size = iPos[0].w; // Stored size here

float3 vAt = particleCenterPos.xyz - cameraPos.xyz;
vAt = normalize( vAt );
float3 vRight = cross( float3( 0.0, 1.0, 0.0 ), vAt );
float3 vUp = cross( vAt, vRight );
vRight = normalize( vRight );
vUp = normalize( vUp );

float3 dir1 = (-size * vRight.xyz) + ( +size * vUp.xyz );
float3 dir2 = (+size * vRight.xyz) + ( +size * vUp.xyz );
float3 dir3 = (-size * vRight.xyz) + ( -size * vUp.xyz );
float3 dir4 = (+size * vRight.xyz) + ( -size * vUp.xyz );
p1 = mul( glstate.matrix.mvp, float4(particleCenterPos.xyz + dir1,1 ) );
p2 = mul( glstate.matrix.mvp, float4(particleCenterPos.xyz + dir2,1 ) );
p3 = mul( glstate.matrix.mvp, float4(particleCenterPos.xyz + dir3,1 ) );
p4 = mul( glstate.matrix.mvp, float4(particleCenterPos.xyz + dir4,1 ) );
// Don't forget the texcoords
const float2 tx1 = { 1,0 };
const float2 tx2 = { 0,0 };
const float2 tx3 = { 1,1 };
const float2 tx4 = { 0,1 };

emitVertex( p1 : POSITION, tx1 : TEXCOORD0 );
emitVertex( p2 : POSITION, tx2 : TEXCOORD0 );
emitVertex( p3 : POSITION, tx3 : TEXCOORD0 );
emitVertex( p4 : POSITION, tx4 : TEXCOORD0 );
restartStrip();
}


Transformers!
Nice and all, but how to use transform-feedback? Here some directions. Not sure if this also works on ATI/AMD cards though…

// Specify target for transform feedback
// Toggle between 2 vbo’s
glBindBufferOffsetNV(GL_TRANSFORM_FEEDBACK_BUFFER_NV, 0, particleVBO [0 or 1], 0);
glBeginTransformFeedbackNV( GL_POINTS );
glEnable(GL_RASTERIZER_DISCARD_NV); // disable rasterization ( = no pixel output to textures/screen)
// Apply shaders & draw the VBO
render_ParticleVBO;

glDisable(GL_RASTERIZER_DISCARD_NV); // Return normal modus
glEndTransformFeedbackNV();

As for the VBO creation, here is one way:

glGenBuffersARB( 2, @particleVBO[0] ); // Make 2 buffers
for j:=0 to 1 do begin
glBindBufferARB( GL_ARRAY_BUFFER_ARB, particleVBO [j] ); // Set target
// Pump array of structs into the VBO
glBufferDataARB( GL_ARRAY_BUFFER_ARB, self.props.maxParticles * sizeof(TVBO_Particle), @part[0], GL_STATIC_DRAW_ARB );
// Don’t forget, specify which attributes to store
glTransformFeedbackAttribsNV(5, @attribs[0], GL_INTERLEAVED_ATTRIBS_NV);
end; // for j
glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); // unbind


Final notes
VBO’s & Transform feedback allows to render lot’s more particles. That still doesn’t fix all problems though. First of all, the performance will still decrease rapidly when looking into a dense cloud of particles where the quads overlap lot’s of times (meaning each pixel gets overdrawn many times).

Then there is depth-sorting. No matter how many particles you use, if your front particles mask the ones behind, it still doesn’t pay off. When using additive or multiply blending methods, this is not a problem. Though you may risk to get extreme bright/dark results as soon as particles overlap on the screen. When using normal transparency, you still need to sort things out. I believe there are methods to sort on the GPU as well, but I never really looked at them yet. Another way might be using multiple particle generators, sort them on the CPU, then render them all to get a combined result.

Finally, I’m not so sure if this technique is also advisable for small amounts of particles. For example, when shooting at a wall, you may only need a handful of debris particles flying around. Setting up a VBO takes some extra time, so either use the good old CPU approach, or use a fixed set of premade particle generators.

Sunday, August 21, 2011

Funf Bier bitte schnell, danke.


Just in time to shoot this pic!

Excuses for the delay. See, I'm a temporarily crippled programmer now. Allow me to explain.


Two weeks ago we came back from our little vacation in Germany's Capital city: Curry Gewürz, I mean Berlin. No, leave the Bratwurst and Heidi Jokes in the trunk. The image of big bellied, mustached beer drinking champs with lederhosen and a hat+feather is a bit false. At least here in Berlin. Which is a shame by the way, but more about that later. Berlin is a modern, big city with modern citizens. Did we really expect something else then? No of course not. Yet Berlin is quite different when comparing it, for example, to our Dutch cities such as Amsterdam or our beloved Breda.

Right after leaving the Haupt Bahnhoff (Central Station), the first things you'll notice are the colossal structures. Berlin doesn't have a lot of highrise like American cities do, yet it's filled with massive blocks and monuments, placed asides the wide roads(no gigantic traffic jams here!). Many of them looking threatening, imposing. Maybe once fulfilling a dark task, in the DDR or WOII era.


Needless to say, Berlin has quite a history. Varying from the Iron Curtain that separated the liberated Western from the communistic world, to the last days of Hitler during the WOII. Speaking of which, it just happened to be that our hotel was placed right on top of Hitler's Bunker. Yep, the site you'll see in the (great) movie "Der Untergang". Don't expect much of it though. The Russian took quite some effort to remove the bunker. Hitler's "grave" is nothing more than a parking lot between a couple of calm buildings nowadays. Only a sign will remind you what happened here. We found this out while playing Red Alert (with the Stalin cutscenes yes), and wondered why there were so many people outside, standing near that sign. Wait a minute… yep, we were playing war games on the grave of one of world’s most infamous leaders.

Soviet war Monument.


Nothing to see here, move along. Our apartment was just outside the picture in the left upper corner. The other picture is not Hitler's bunker btw, it's our Radar Station testing map. We're starting to get some objects to decorate the place with.

Berlin makes you think about war, and the more recent DDR era that forced its people into the socialist ideology with instruments like the Stasi. The remains of this history are spread throughout the city, giving a grim look over some parts. But of course, there is more than oppression and bloodshed; Berlin didn't stood still last decades. An excellent subway system, Modern office buildings are placed between the old Stasi offices, hip restaurants pretty much everywhere. Unlike some ex-communistic cities I saw in Poland, Berlin looks fresh, clean and structured. Certainly not as if the KGB is still watching there. Although I didn't like Checkpoint Charlie. A few sandbags, American flags, two actors, and... a fucking macDonalds 4 meters further. The ultimate price of a Western society.

You can still see and visit many remains, including the Wall and the evil looking Reichstag building. Yet, just like with Auswitz Birkenau, it's hard to get a good feeling of what really happened. Time erases the past. Then again, did you really think 5 guys would visit Berlin for history lessons? I can dream operation Blitzkrieg and Barbarossa after seeing 6.000 documentaries already. No, what healthy Dutch boys really want is beer. Lots of it.


Meet modern Berlin. As a friend would say, this looks like an IPad3 or something.

And that's where we got stuck a bit. Instead of 130 KG feather-hat, mustached lederhosen guys sitting at a table with roasted pork and beer, we only saw modern, cozy(not) purple LED-light bars. Music volume -4, only a few people, closed pretty early... Aye, that's not what are used to. In Amsterdam, you can get drunk in 60 seconds as soon as you arrive in the center. In Berlin, you need a sniffing-dog specialed in tracing beer, because this large city doesn't really have all stuff concentrated at one central point. The bars are sure out there, but spread or well hidden. And in most cases, not really alive. Although I liked the fact that Berlin people are calm and friendly, the noise of 600 drunken people and the feeling you can get involved in a barfight any time, "engages" here in Holland. In Berlin, I often had the idea that we noisy, farting, burping, belging, laughing idiots were annoying for other people who try to have a calm conversation. But I also had that feeling in France. And in Belgium. And a bit in Prague...

Well, making noise, trying to get drunk, and waking up 06:30 on the floor with a flower bouquete in my underpants (yes, that happened) is maybe just a Dutch thing... And British probably. I'm sure there is a lot more to find in Berlin, just have to dig a little bit deeper. Other than that, we had a good time. And a nice bonus feature is the price. Whether you need beer or a Rumpsteak at a restaurant, Berlin is cheap compared to other Western Europe cities. Same goes for the hotel.



And... Friday actually delivered what we want when it comes to lederhosen, beer and schlager (and Rammstein): Berlin's international Beer-festival! Dozens of beer stalls, tables, music, and würst. Hurray! With as a grand finale a broken foot. Drunk and satisfied, we went home and waited in the Metro station. I felt down somehow, and hurted my foot badly. My friends had to transport 95 kg of drunken flesh through the wide streets of Berlin. Luckily it happened on the very last night, but a few days later it turned out that my metatarsals were broken at 3 or 4 spots. End result: I’m driving in a wheelchair with a laptop between the harvesting and tabletting machines like Stephen Hawking now. Except that Stephen is not so stupid to drink and break his foot probably.

Yeah keep laughin, but not for long anymore. Not everyone likes to wear Lederhosen by the way.

Next time, back on games