art with code

2015-01-13

Opus Live Wallpaper

I ported a bunch of the fhtr.org effects over to Android to use as a live wallpaper. The wallpaper is available on the Google Play Store as either a $0.99 version or an ad-funded version (hey, there's also a small fireworks wallpaper with a web preview). My total income from these over the last month has been a bit less than $5, so, well, it's been more educational than anything else :D

The effects look like the pictures below or the video above. I like having them as wallpapers, gives a nice feel to my phone. You probably need something like an Adreno 330 to run them well, so phones like LG G2 and above.

Porting the shaders over from WebGL was easy for the most part. There were a whole lot of performance tweaks that I had to apply. One of the most important ones was rendering into an FBO at a lower resolution and then upscaling the FBO to screen res. With HiDPI displays, the difference between full res and scaled up is not very drastic.

Another technique I used was rendering at a lower framerate. The prob there is that you want to keep the main UI interactive while you're rendering. If you do it naively with "render frame -> wait 2 frames -> render frame -> ...", and the "render frame" bit takes longer than 16ms, you'll cause the main UI to skip frames. Which is bad. The solution I arrived to was to render a part of the wallpaper frame during the main UI frames, then display the finished frame in the end: "render 1/3 of frame -> render 2/3 of frame -> render 3/3 of frame & display it -> ...". This way I can keep the main UI interactive while rendering the wallpaper frame.

But we're not out of the woods yet! Some wallpapers have a central part that is very heavy to render and edges that are cheap. If we split the frame into e.g. 3 slices, one of the slices would take the majority of the time, and potentially cause the main UI to skip frames. So we need to find a split that distributes the work equally among the UI frames. To do the partial frame rendering, I slice the frame into 8 px vertical stripes. On each UI frame, I render the wallpaper stripes belonging to that frame (frameNumber % numberOfUIFramesPerWallpaperFrame == 0). As the UI frame number increases, the renderer moves across the wallpaper frame, drawing it in an interleaved fashion. This gives me a fairly even split of work per frame and gets me a consistent frame rate for the UI.

If you have a try at the wallpapers, lemme know how it goes. Would be super interested in hearing your thoughts.

No comments:

Blog Archive