The demo I am about to show, is a parallax technique I have been working on. I will not share any code at this point, but I can explain the techniques, and answer any questions.
The video can be seen here
The idea is to create a fully deformable terrain, with a total of 5 parallax layers. When doing this many parallax layers, the final number of pixels which gets rendered on the screen, easily exceeds 10M pixels pr frame on an iPad3. The thing is, that if you need a bit of freedom to move the camera around, the number of pixel which gets drawn more than once, almost explodes. I wanted to avoid that.
Furthermore. As the terrain is zoomable with a factor 8, it puts quite a strain on the image sizes, as we of course did not want pixelation when zoomed all the way in. And even worse than pixelation, blending artefacts from scaled textures, causing dark outlines.
So the basic idea ( to avoid drawing any pixel more than once ) was to draw the entire game in only two triangles, drawing any pixel exactly one time.This of course needs a lot of textures for the shader. In this case, the maximum of 8.
2) Parallax 0
3) Parallax 1
4) Parallax 2
5) Object layer
6) Front layer
7) Terrain crust texture
8) Mask texture
The deformable terrain is made, using Objective Chipmunk. The terrain mask is stored in a CGBitmapContext, allowing Chipmunk to scan the pixels to create the terrain. Deformation is made simply by drawing to the CGContext. Several colors are used. The red channel defines the actual terrain surface, and is made with a heavy blur. The blur is then used to create texture coordinates for the terrain crust. Once again thanks to the guys behind Chipmunk, for the inspiration to this. The crust is masked using the green channel. This is made programatically, so that different types of crusts can be applied. At this point, crust is added to terrain pieces under a certain slope.
Rendering the entire terrain in a single quad, has the drawback, that no matter where ( and how much ) the texture is shown, it is drawn on the entire screen. After doing a bit of math on this, I realized that nearly 50% of the render time, was spend mixing pixels from outside textures.
So I dynamically broke the single terrain quad into horizontal strips, based on how many parallax layers covers the strip. The top most strip will in most cases only be the skybox, so that piece only needs to render the skybox texture.
Having 5 layers, this gives a total of 32 combinations. Even if some of these combination never will be called, I created 32 shaders ( basically creating one shader, and then just commenting stuff out ) and then use the correct shader, based on the layer combination.
This nearly doubled the framerate, and iPad2 + 3 is a solid 60 fps.
The last thing I wanted to avoid, is the blending artefacts around scaled objects. Having had a close look at Dreamworks Dragons ( which sports some really fancy parallax ), I realized that they solved the problem by adding dark borders to close objects, and disable texture blending on far objects. This results in a less crisp loop, and noticeable pixellation on far objects.
My approach with rendering the entire terrain in one quad ( breaking it into strips really doesn’t change the basic idea ) has the benefit, that I have full control of how the rendering is done, and how the blending is done for all layers in a single shader. If I render front to back, in stead of back to front, I have the huge benefit, that I can blend up against the background, and not up against some unknown layer behind. So by adjusting the background color, I can hit a point where the blending artefacts almost disappear. The video doesn’t really do it full justice, but you can see in some of the parts where I zoom in, that the terrain is very crips, and that there is no pixellation what so ever.
If you ask me, it looks damn good.