Monday, October 24, 2011

Up yours


Tactical plans sir.

Another big name wiped off the Risk playboard. Saddam, Bin Laden, now Ghaddafi (or whatever his name is spelled). Who's next? Il Kim 3000? Obama? Don't know what to think of Ghaddafi's fall. I'm “glad” it got taped on film so we don't have to get in doubt with conspiracy theories again. Well, what say about it… He didn't give a fair trial for his opponents either, and dictators generally suck anyway. Then again, Libya was relative rich and developed compared to some other countries in the region. Iraq turned into a hell-pit when Saddam got chased into a hole, and I don't trust the extremists who are ready to jump into this Arabic Spring either. From a dictatorial system to a deep religious system... not my cup of tea.

I hope the youngsters who started these demonstrations can really create a better future without chaos, war, dictators or religious bearded dresses telling them how think, what to do, and what not to do. A tolerant place based on freedom, tolerance, and common sense. But the problem in these locations is that the word usually goes to the one with the biggest sable/AK-47, rather than a democratically chosen intellect with vision. Although… democracy has become a joke in the Western world as well. Can't remember anyone asking me about whether we should join the war in the mid-east, give more power to Brussels, how to deal with near-bankrupt countries in the EU zone, or if we should "free" Libya (for their own (oil) interests). A “No.” from the people still gets turned in a “no but, Yes - with some chocolate sauce”.


The big guys play their game anyway, no matter what we think of it. As long as we're happy with our house, car, widescreen TV and “What’s in Store!”- Bodytoaster Pro, they can keep milking tax and wipe their ass with it in any that pleases them. It's the 1% versus 99% story. A small elite of... fuckers, decides what happens in the world. Whether Ghadaffi should deliver oil, or sleep in a supermarket cooling cell. If banks should be saved whether they screw up or not. When & where to fight a cozy war to bring “Democracy”. Which other cool overpaid jobs they can get via the Old Boys network. And what we, -99%-, of tax-cows should know and do to keep their thirsty machine running. The Bible sin "Greed" is a nice summary of it all.

That's where the Occupy movement comes from I guess. Sounds I'm an anti-capitalist too. Well, not really. In my opinion, those who work hard should earn more than those who lay in their bench every day, bitching about everything. And a bigger salary should motivate people to use their talents instead of putting everyone behind the same factory conveyor belt. Listen up, there's no such thing as a free lunch. Instead of complaining or envying others, you'd better try to accomplish something yourself, and accept that there will always be people with more money, more women, more success, and more golden teeth whether they really deserve it or not. BUT, a system with a small superrich elite that does dark, unverifiable things stinks. But hey! What are you gonna do about it? Unless we really start rioting and build improvised tanks and Anti-Air pickup trucks, the elite probably doesn't care less about another demonstration. Hence, five days later the mess gets cleaned up by a couple of (hard working) garbage men, paid by our own tax of course. Face it, we know too little and have too much to lose to stand up against it. Bend over please.

I don’t see that happening at the Occupy demonstrations… By the way, those Libyans had some excessive welding classes last months!



Enough politics.
So how's the progress on that next little movie? ...Movie? For those who didn't know yet, we're trying to show a (tech)movie end this year. Or begin 2012 in case things get messed up, but the goal is to give you a Christmas present. Don't expect a "cinematic"-horror-gameplay movie though. It's merely a flythrough, showing some engine graphics stuff, and most of all, the audio, 3D and texture work that has been done by the T22 team.

No secret, the goal is to attract some more 3D/Texture/Concept art people with that demo. Cause we really need it! In the Blog statistics (love them), I saw one was Googling for "Tower 22 release date". I bet you can find a T22_Install.exe on some murky Torrent website within a few years, but we really still have to start on this game! That's right, other than the assets you've seen in this Blog, a half-working engine, and a story + ideas on paper, there is no game content yet! The reason is pretty simple. I want to start on the game when:

- The team is big, talented & motivated enough
- The engine works "good enough"
- Development tools are "good enough"
- All the design & plans have been clearly documented
* In the meanwhile, we build 1 or 2 more demo’s. At least one is planned for 2012

In other words, I don't want to build Tower22 on a fundament of shit. The good news; the engine + tools are going pretty well, the paperwork is scheduled, and the team is growing slow but steadily. Hopefully the Tech-Demo gives it another boost. Making a game isn't easy, so compare it with getting the Titanic into movement. But I have faith in it!

Do you know what's annoying? Rendering white paper without getting blinded by HDR bloom.

I didn't answer the question yet. How's the demo progress going? Well, a whole listing of objects(chairs, lamps, junk), textures and audio is still there. But each week I can check three to five assets, so I think the scene has enough material to look and sound properly within two months. No "borrowed" Halflife2 assets this time! As for the engine, there isn't that much noticeable improvement. The sound engine should hear the same with FMOD. The compressed DDS should look the same as the uncompressed TGA's did (I damn hope so!), and upgraded input modules aren’t going to produce anything visual either. There are some noticeable new effects though (asides from quite a lot bug-fixed and little improvements):

- GPU Particles (with lighting)
- Water
- Ice shaders
- Wall overlays (dirt, cracks, snow, frost)
- Anti-Aliasing
- And stuff I probably forgot

Currently I'm playing with realtime water-fluids to replace the stupid rolling ripple texture with something better looking (and for another water article :p). But I'm not so sure if it will make it before Christmas. We'll see. The biggest improvement should be the recording quality! I haven’t been looking for a better way yet, but let’s see if I can use an external device to record the movie so the CPU won’t be hogging and choking the sound.

The (sharp specular highlight) edges on this stinky chair and the drawers in the background are anti-aliased with FXAA. But I’m not 100% convinced. Either FXAA isn’t effective enough (and making it more powerful will blur the entire screen), or the shader has a little bug…

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”