19 April 2016

Drawing game for mobile

In Kweetet there is a donkey in Initia (the main scene) called "schildersezel", which is Dutch for a painter's easel. "Ezel" is in dutch actually a donkey and it's a painting donkey, so there's the pun.

When you click on the sign above the donkey you start the drawing game of Kweetet, which you can use to create drawings that are displayed throughout the world, or that you even need to complete certain missions.

In this game you can either draw lines or use a flood fill. The code for drawing the lines is based on Aron Granberg's UnityPaint. For the floodfill I used an algorithm found on the internet, but I lost the original link.

I also used the floodfill algorithm for the lines; that way, when drawing lines, the color does not cross a black line, making it easier to stay within the lines for small children (and basically anyone who wants to draw between the lines with thick fingers on a tablet).

There is only one downside to Granberg's implementation: the algorithm has the texture in memory as an array of pixels which is manipulated by the algorithm and when done painting there is a call to SetPixels and Apply on the target texture, which copies the pixels from RAM to VRAM. Aside from being a memory hog, it worked in the webplayer and standalone, even on webgl. Some older devices were not capable to run it though. Let alone mobile devices. On mobile devices, when drawing lines the fps drops to +/- five. Uploading a texture from CPU to GPU memory is not very performant but you can get away with it on computers. On mobile devices on the other hand, it appears not.

We had a couple of students at the office who's task was to find a better solution and they suggested to use GL calls directly on the texture, so we wouldn't need to upload anything to VRAM.

The flood fill algorithm scans the texture in horizontal lines finding the left and right edges and coloring the pixels in between. So I changed this to drawing lines between the found left and right edges and using GL calls to draw the pixels in a render texture. The coloring code (with a Gaussian falloff) needed to be applied on the GPU, so we used a custom shader that executed the exact same rendering code, but now directly on the GPU.

Result: 60 fps all the time! Checkout this example.

Ps: I know the drawing in above example is probably copyrighted by Studio 100, but I love the childishly innocence of it so much that I use it anyway, it's too beautiful. They'll contact me if they want to have it removed.

The unity project of the example can be downloaded here.

Edit: I uploaded new versions of the webgl demo and the project, because I noticed that on some pc's and mobile devices, there was a problem with the fill algorithm. It appeared there was a one pixel offset on the top of the fill surface. After quite some searching I discovered that this is caused by a bug that has been reported and reproduced, but not yet fixed in Unity.

Edit: This project has now been integrated in my general UnityToolset project on bitbucket.


Edward Rowe said...

Thanks for the post and code samples! Very helpful. I'm doing something similar and I'm wondering if you have an intended license for the code. And if it permits, would you want any contributions to the repo?

Alex Vanden Abeele said...

Hi, I've just added a license document to my repo, in case anyone else would have the same question. I use the wtfpl license for all software posted on my blog, so feel free to use at will. I'm not opening the repo, but feedback is always welcome! I might upload an update to 2018.1 of this project soon.