Tech Interview: WipEout HD/Fury
Studio Liverpool on re-igniting the 1080p dream.
The challenge was not as significant as it might have been. Because we were essentially iterating PSP assets, increasing texture and geometry resolution over time, the process was really just to see how far we could go, then stop. Because we had existing technology from Formula One: Championship Edition that we'd already spent a lot of time improving, as well as first-class support from our internal technology groups, it turned out we could go quite a long way before we stopped. Only the ships in WipEout have LOD [different levels of detail according to distance from the camera - DF], and the lowest LOD for a ship is around 10,000 polys (the highest are around 30,000 polys). Some of the environments are around 1.5 million polys.
1080p (1920x1080) vs 720p (1280x720) translates to 2.25x the buffer space required for 720p. Therefore more memory is required for the render buffers meaning we have less available for textures and geometry etc. We render with 2xMSAA in 720p, so there's not a huge difference in memory footprint - actually 1080p needs less memory because we don't have to do the multisample resolve so the alpha-to-coverage buffer isn't really needed.
Alongside the main framebuffer we also use other buffers for post-processing effects which although not at 1080 are still quite sizeable and due to the sheer number of pixels we need to process the fragment shaders need to be highly optimised.
WipEout HD uses a fairly sophisticated shader system - we have many possible versions of each shader (not many people may have noticed, but there are real-time shadow-casting spot lights on some of the tracks!) and we really only want to hit every pixel once if possible - this means we need very fine control over how each shader is built since that single pass over each pixel needs to do the minimum work necessary. The same system also allows us to intercept and modify parts of the shader that are normally controlled by the art team. This is how all of the zone mode effects are implemented.
We also make practical compromises - full scene shadow-mapping would require drawing the scene twice. Reflecting the environment would require rendering a representation of the scene six times into a cube map, possibly for each ship. We use smoke and mirrors to achieve both these effects. This is often far more work than just having a unified system (eg. multi-pass or deferred) since we need to invent a clever solution for each effect we're trying to simulate. Some effects like the reflecting water on Moa Therma and the refracting tunnels on Vineta K don't have a clever solution - we just do them the same way as everyone else (although we cheat a little by using lower bit depth reflect/refract buffers).
When designing particle and geometry-based shader effects in 1080p we have to be very careful to avoid overdraw and reduce their screen space as much as possible as it really hurts the frame rate. Using pre-processed PVS Data for each track really helps us to reduce the amount of triangles we need to process when we come to render the scene. For post-processing effects such as blurs and blooms we used down sampled buffers to reduce the memory requirements and fill rate.
All particle effects in F1:CE were rendered at a reduced resolution to help control fill rate issues - in WipEout HD particles are always rendered at full resolution. This saves us having to perform an upsample and merge operation all the time even when there are hardly any particles on the screen, and this is where the framebuffer throttling helps. It also means that the image quality for the particle effects isn't compromised.
Definitely, the SPUs are a godsend. We offloaded as much as we could onto the SPUs: physics collision, particle simulation, dynamic lighting, audio, data decompression and particle and trail rendering. We also made good use of the PS3's Edge tools which utilise the SPUs.
As well as relieving the GPU, in WipEout HD the SPUs perform almost all of the CPU's rendering operations such as inserting commands to set render state, set up shaders and issue geometry rendering commands.
We used Edge Geometry for triangle culling to dramatically reduce the vertices we need to process, and because it's a framework it's possible to add our own additional effects during this stage - all of the dynamic lighting effects are computed by the SPUs on the vertices that passed the visibility checks. WipEout HD supports up to 256 of these lights of any size (although it's rare to have more than a few active at once). They have since added Edge Post which provides greater support for SPU implemented framebuffer post processing effects.
Reducing the horizontal resolution dynamically allows us to hit our target 60FPS when the scene complexity literally explodes during heavy weapons fire. This means we don't have to compromise the overall graphical quality just to account for these sporadic maximum load scenarios. The drop in resolution isn't really very noticeable and we feel it's a worthwhile trade off.
We dynamically alter the horizontal resolution from 1920 to 1280 in steps of 32 pixels. Even when the game is paused and we modify the resolution in the debugger it is very hard to see a change. It is not enabled at resolutions lower than 1080p. The throttling is only allowed to change by 32 pixels each frame (either up or down). The strategy is not to predict when we will overflow a frame (which is somewhat impossible), but to recover as quickly possible if it happens. On some televisions you can see that the tearing is actually present all the time in the top few pixels of the screen. This is due to the software v-sync implementation used in WipEout HD - this is not 'framing out', it's just missing the true v-sync by a few pixels.