"There's a saying that states: 'The road to hell is paved with good intentions'. There's hardly anything that better describes communism than that. All good hopes and dreams of justice and equality have ended in oppression and dictatorship."
- Peter Eriksson, Green Party of Sweden
More pages: 1 2 3
My first 1K demo
Sunday, February 13, 2011 | Permalink

Even though I have written demos for over a decade now, I have never been part of the demoscene, never gone to a demo party, and only once in a long while have I ever really run the demos that come out of the demoscene. This tends to surprise people when they get to know me if they happened to have followed my site before. In general, I've been more interested in pushing the boundaries in terms of visual quality and performance in general, rather than squeezing the most out of a particular machine or shoehorning things into tiny executables. I did at some point in my early years give 4K demos a try, maybe around 1999 or so, but I gave up pretty quickly. With even an empty main() I got an executable that was 27KB IIRC. So I figured I had a few things to learn. Well, skip forward to 2011 and I got a renewed interest in the subject, and after a little research on the subject I was up and running with a simple OpenGL app that compiled to like 950 bytes or so. Given the small size I thought it would be cool to aim for 1K instead of 4K since that was within reach.

So I made another Mandelbrot viewer, since it's something relatively compact I thought I would be able to do quickly. A Mandelbrot viewer is perhaps the most original idea, I mean, it's not something that hasn't been done before, in fact I've done several myself before, although this one has the smoothest gradients I've managed to make so far. However, the project took far more time than I had originally anticipated. Once it was visually and functionally complete, I was somewhere over 1400 bytes. In the beginning it was rather quick to trim it down, shaving off dozens of bytes with every change. Until I got down to like 1100 bytes, after which I was happy to cut off another 5-10 bytes after an hour's work. Eventually after I got down to 1045 bytes I got kind of stuck and rewriting it all in assembly might have removed another few bytes, but I wasn't sure if it would be enough to shave off 21 bytes, so instead I changed the functionality a little. Thus there are two versions of the executables, one that's small enough to fit within the 1K limit, and one that contains the originally intended functionality, and thus is like 55 bytes larger.

If anyone knows any good tricks for slimming it down further that I might have missed, please let me know.

Update 2011-02-14:
Some sources I used to get started on this project:
1k/4k demo framework and examples
Crinkler
Crinkler secrets, 4k intro executable compressor at its best
Graphics Size Coding

Name

Comment

Enter the code below



NitroGL
Tuesday, February 15, 2011

Any special OS requirements on these?
They just crash on my NV30 XP laptop (GL2).

Humus
Tuesday, February 15, 2011

Nuninho1980: At 1024 bytes you cannot afford the luxury of enabling vsync. Setting the resolution would be a higher priority, and I cut that out as well.

NitroGL: Nope, but I have only tested on Vista 64, so there's a chance it's broken on XP. Or the driver might have trouble compiling the shader to the NV30 hardware.

sqrt[-1]
Wednesday, February 16, 2011

That is cool - I am going to have a go and see how small I can make a WebGL equivalent.

Seven
Wednesday, February 16, 2011

While Crinkler is without a doubt the best compressor for 4Ks, there a better alternative for 1Ks: 1kPack. You can find the download link here: http://www.pouet.net/prod.php?which=52796

It works by compressing the executable as an image, which can be decompressed by DirectX. So your intro does not technically contain its own decompressor anymore. Compression is worse than Crinkler, but for very small projects this is compensated enough by the no-decompressor savings.

And for 64K there is kkrunchy, which dissassembles your code and re-packs it as separate streams of prefix bytes, opcodes and operands for improved compression rates... As you can see, the larger your intro, the more complex your techniques can be

Also useful (and fairly new) is the Shader minifier (formerly GLSL minifier but it does HSLS too now):
http://www.pouet.net/prod.php?which=55176
This rewrites your shader, renaming the variables and functions for improved compression. It already beats several hand-optimized party winners.

Humus
Monday, February 21, 2011

I looked at 1kPack, but it appears to be made for asm coding. I don't feel motivated to rewrite it in asm to try it out.

I gave Shader Minifier a shot though, but it didn't save me anything over my handtrimmed shader. However, I noticed it got rid of the brackets in my while-loop, which was a useful idea. So using that trick and a little manual handtuning again I saved another 3 bytes. Yay! Not enough to bother making a new release though.

Seven
Thursday, February 24, 2011

Your shader seems very compact, so there's probably not much to gain there. But I see you're using quite a few floats (zoom locations f.e). By default, Crinkler will compress these loslessly, because all bits might be important in the context of a demo. But for many things in a 4k/1k such as camera paths or object locations, a reduced precision is good enough. So check the TRUNCATEFLOATS option of Crinkler if you're not using it already. Also, you're using some float constants (1.0f / 8192.0f) that might compress better if replaced by compress-friendly approximations. See iq's list here: http://www.iquilezles.org/www/articles/float4k/float4k.htm

Humus
Thursday, February 24, 2011

Yeah, I'm aware of those. I didn't use that flag, but did the equivalent work manually instead. All those numbers are chosen specifically because they are very compressible with most of the low bits as zero. I wrote a small piece of code to generate compressible coordinates with "interesting" visuals. Then I manually went through the whole list of a couple of hundred candidates and kept good ones and threw away not so interesting ones, and then kept going until I had a few favorites left and got under 1024 bytes.

As for 1.0f/8192.0f, that's actually a very compressible number (0x39000000).

sqrt[-1]
Saturday, February 26, 2011

It took longer than expected, but I did manage to squeeze a port of this to WebGL in 1K (using some nasty hacks that may break in future browsers)

http://dtrebilco.googlecode.com/files/WebGLMandelbrot.zip

Tested in the Chrome build 10.

More pages: 1 2 3