Character customization is a great asset for games today, especially for multiplayer online games. Players love customizing their characters and give them a unique look and tailor things to their liking. We recently explored a few methods for real time texture painting for our kids’ game, DrawFish. The game allows kids to paint a fish to their liking and play with it as it swims and jumps in the pond.
Texture Painting Approaches
Let’s see how we can paint textures at run time in Unity. The most straightforward approach is to read raw pixel values from the texture and modify them at runtime.
Updating Raw Colors
This approach uses GetPixels to read the color values in the texture, modifies it as per user input and finally applies it back using SetPixels.
The main overhead in this approach comes from the Texture2D.Apply call. It actually applies all previous SetPixel and SetPixels changes. What Apply does behind the scenes is that it uploads the texture from the CPU to the GPU which is going to be very slow if you want to run at 60 FPS or even 30 FPS.
Using Render Texture
Render Textures are special types of Textures that are created and updated at runtime by using a Camera to render into them.
Render Texture Setup
To simulate real time painting using Render Texture, we will set up a Quad containing the original texture to be painted with an orthographic Camera pointing right at it and rendering into a Render Texture. This Render Texture is then used as a Texture on the fish.
The quad in the background should have an unlit texture to prevent lightning artefacts on the texture. The original texture rendered on the fish will have lightning enabled, though.
The next part is to map the clicks on the fish to a point on the Texture. For this, we will add a Mesh Collider to the fish and use Ray Casting to map the 3D world coordinates to the 2D UV coordinates for use on the texture.
Now that we have the position where we want to paint on the texture, all we need is to put stuff in front of our quad so it appears on the render texture. We can instantiate anything we want to control what kind of paint we would be doing. Create a Sprite with the following image:
To paint different colors, we can just change the Color property on the sprite object. This also allows us to take advantage of static batching in unity to reduce draw calls to batch the sprites together.
Merging Brushes Into Texture
We can see the fish being painted in real time as soon as we instantiate the brushes in the scene. But we cannot keep on instantiating objects in the scene indefinitely or we will soon run out of memory. After we reach a certain point where a lot of brushes have been instantiated, we need to combine all of them into the texture being rendered on the quad and remove them from the scene. The painting can then resume by generating more brushes in scene until we reach the threshold again.
Here is an example of how the painting works on the render texture and how it looks on the fish.