Creating App Store artwork for Armageddon Wars

This is how I created the main “icon” for Armageddon Wars. The main App Store icon has to be 512×512 pixels, but usually is displayed much smaller, so the image had to look good even scaled down 10 times.

The shape of a painting is what most affects the composition. If you get this right you can get a great dramatic effect, but you need to start out very abstract. So, what I do is just start drawing random abstract shapes, until I hit on one that I like:

shape 1

shape 2

finally, this is the one I choose

Once you have a good shape you start adding details.

I had some tank models and city ruins done in Max, so I thought I would take advantage of that and made some test scenes in Max. This would also ensure that I got the lighting correct for the scene.

First, I had the turret facing to the right, which was ok, but everything was too dark because the light was positioned too low and far back.

So, I fixed the light and changed the turret and also have it almost facing camera.

Then I imported this into photoshop, added a background of an inferno (that I took from a photo) and started working on the barrel.

I started painting over the tank and buildings, making the turret structure more well defined. This picture had to recognisable at very small scale, so I made the outline distinct.

I added details on the tank and drew some burning ruins in the distance.

Those ruins weren’t that great, so added some burning skyscrapers instead.Then I added some smoke for the near foreground…

and then I rotated it – if you remember the original sketch was rotated as well, but that was somehow lost in the process. And that’s it!

Advertisements

Visual Studio warnings

I found it useful to change some of the warnings generated by Visual Studio.

For instance, this statement:

if (num = 10) { doSomething(); }

Generates a warning, but I cannot see any case where this would not be a bug. So I change this warning and some others to errors: like this:


#pragma warning (error: 4715)
#pragma warning (error: 4706)
#pragma warning (error: 4553)    // '==' : operator has no effect; did you intend '='?
#pragma warning (error: 4150)    // deletion of pointer to incomplete type
#pragma warning (error: 4390)    // empty controlled statement found;
#pragma warning (disable: 4996)  // openf is dangerous (not!)

Now, there’s no way you can ignore it. By the way, there is a bug in Visual Studio, sometimes it won’t flag warning mentioned above at all.

Some old performance tricks

The documentation for the iphone’s VFP processor says that all floating point instructions take 1 cycle, apart from divide and square root, which take 15 cycles.

This leads to a very obvious optimisation, to cache your divide operations.

In other words if you have code like this:

float fl = 1.0007f;
for (i = 0; i < 16; i++)
matrix.Set(i, matrix[i]/fl);

you can increase performance by doing the divide outside the loop:

float fl = 1.0f/1.0007f;
for (i = 0; i < 16; i++)
matrix.Set(i, matrix[i]*fl);

I measured this and found that it does indeed make a big improvement.

Also, I thought it would be interesting to try out the old Quake inverse square root trick.

float InvSqrt(float x){
   float xhalf = 0.5f * x;
   int i = *(int*)&x; // store floating-point bits in integer
   i = 0x5f3759d5 - (i >> 1); // initial guess for Newton's method
   x = *(float*)&i; // convert new bits into float
   x = x*(1.5f - xhalf*x*x); // One round of Newton's method
   return x;
}

This code works on the iPhone, but the results are less accurate.

float fl = 2.0f;
result = 1.f / sqrt ( fl );   // gives 0.707106769
result = InvSqrt(fl);   // gives 0.706930041

the actual value should be 0.70710678

I measured the performance and found that it’s a touch faster, but not much.

OpenGL Features Removed from iPhone

Full screen anti-aliasing is a feature that greatly improves the graphic quality of any game and is supported by the powervr chip. Unfortunately, you don’t have access to the feature, because the iPhone does not use EGL. Instead it uses the framebuffer extension to bind to a surface and in order to enable anti-aliasing you have to call eglChooseConfig with the EGL_SAMPLE_BUFFERS parameter and this is not possible.

Funnily, enough I found a project that appears to use EGL with the iPhone: http://code.google.com/p/iphone-dj/

However, looking a bit close I see that the egl.h file does not even exist in the SDK, so the code in that project should not even compile (pretty wierd that).

This also means that the pbuffer isn’t supported, as that is enabled via eglChooseConfig as well. And to top this off I also heard that the GL_IMG_vertex_program extension is disabled (I think this prevents you from using bump mapping and cartoon rendering – as demoed in the powervr sdk)

Edit:

I reciently discovered that there exists an unofficial iPhone SDK, which includes egl. This is probably what iphone-dj was using. So, you probably can get anti-aliasing working if you don’t mind using an unofficial SDK.

Edit, 7 Oct 2010

Apple seemingly have resolved this in iOS4. They’ve implemented MSAA using a extension –

glResolveMultisampleFramebufferAPPLE.

However, there is a catch, it’s implemented in software on older devices (read slow) and with shaders on newer devices (but using more memory). The PowerVR MBX manual says the following:

…Because POWERVR is a tile-based renderer, no extra memory is required for the frame and depth buffers. i.e. they will keep their original size during the whole process. What happens in the hardware is that more tiles are rendered to match the super-sampled size but the scaling-down process is transparent. This is a clear advantage compared to immediate more renderers, which have to allocate precious video memory to cater for the super-sampled frame and depth buffers.

So, basically on older devices – where we are stretching the limits of the GPU – we have to make do with a software MSAA, even though it’s normally available implemented in hardware for free and without requiring more memory.

Rendering models with transparent textures

I was having problems rending low polygon trees in my scene. It was because they used transparent textures which are always problemic. I found this artical that helped me greatly:

http://www.sjbaker.org/steve/omniv/alpha_sorting.html

The solution was to render all opaque objects first, then do:

glAlphaFunc(GL_GREATER, 0.1f);
glEnable(GL_ALPHA_TEST);
and now every thing renders perfectly

Developing iPhone apps with Visual Studio

Origonally I thought XCode was pretty good, indeed it does do somethings better than Visual Studio. However, the support for c++ is lacking, especially if you use templates. XCode can’t display template variables in the debugger window, nor does “Intelisense” work. One of my  projects has a tonne of template based classes, so that’s what pushed me to see if I could do the work on Windows instead.

The PowerVR SDK comes with a Windows OpenGL ES emulator. It didn’t take me long to get my code working with that, because all my code is portable: c++, stl and OpenGL. Straightaway my productivity doubled. So, now I do the implementation and debugging on Visual Studio and periodically switch to Mac to make device builds.

more improvements

I did some more work on my engine.

Implemented redundant node removal and made the class hierarchy more logical and added compressed textures.

The result was that I reduced the frame time to 53ms from 63ms (presume that’s mainly because of reduced nodes)

Also discovered, that just by building on Mac that my character’s face renders correctly (I could have sworn that it wasn’t like that on Windows)