Painting application on the GPU

Hi,

I have been playing around with a CPU implementation of a painting application. The tools I want to implement are pretty basic paint, floodfill, eraser and do/redo. My platform is android so I’m using opengl-es.

My implementation is pretty slow when using large images because CPU/GPU work is not balanced and we have the always dreaded bus bottleneck when downloading/uploading textures. I have tried to add a “Tiled” implementation to split the canvas, I want to draw on, into smallerer textures and consume gpu bandwith in a more optimized way but this produces too many drawcalls (>20) because I have to create a sub texture from the big one.

Could anyone be so kind to point me in the right direction here? I don’t want/need implementation details but some guidelines on the elements you would use to implement a tool like this on unity. For example, would you use shaders instead? (I have been playing with the Graphics.DrawTexture without success). Would you use some kind of Render to texture?

Come’n guys let’s discuss best techniques to build this kind of app.

P.D. I know there are some painting apps templates on the asset store but I would like to implement this myself. On the other hand, most of them are not taking advantage of the gpu and just using setPixels/getPixels. I have also been checking the entry by Aron arongranberg.com/unity/unitypaint about unityPaint but again, everything is done by the cpu and it is pretty slow.

Cheers.

It would be by far more performant for you to use a render texture and to let the GPU do the drawing, especially now that render textures are available in the free version of Unity. That will of course entail a texture size limit based on hardware support, e.g. 2048 or 4096 maximum size… but if that’s ok, this will be hugely faster than the whole uploading of texture data.

I know what you mean about the draw calls… trying to split the uploads into a grid of texture unfortunatly requires a separate material for each and thus a draw call, and beyond a certain size this adds up really quickly. It can help with only having to upload a smaller part of the display each frame, but still… generally speaking the cpu-based processing and upload bottleneck will be several times slower than rendering witht the gpu. You’d have to just generate some geometry in the shape of the object you want to draw, draw it with a camera to a render texture, then draw the render texture to the display with another camera.

1 Like

Hi,

Thanks a lot for the insights. Funny was that I was reading another thread of yours about related stuff :).

Would you mind commenting how would you create the erasing tool using this GPU/RTT method? And the flood fill? I think flood fill will be better to do it in the cpu side.

Again, thanks for taking your time to bringing some light.

Cheers.

Flood fill is a complicated algorithm requiring you to read individual pixels randomly. The GPU side of things is not well designed for reading data. You’d be better off grabbing the whole thing into the cpu side and doing it there.

Erasing… as in, drawing some background color?

Hi,

This is exactly what I was thinking about the flood fill thing.

Sorry I did a mistake when asking about the erasing tool, I wanted to mean do/redo. I mean, I see 2 ways to do it here.

  1. Just have a stack of x actions and when I want to undo, I clear the texture and repaint the numbers of actions -1.
  2. I grab parts of screen (bitmaps) as user paints and save it for later blit when repainting.

1 seems to best fit when working with gpu, 2 seems easy but lota of “grabbing all screen” actions must be perforned to keep modified bitmap rects on RAM.

Have you implemented anything like this?

Cheers.