I am currently working on painting functionality for a Unity iOS game. I have gotten it working, but its a little slow so i am working on optimizing it.
My current problem is with the brush method, here is the relevant code so far:
private void Draw(Vector2 canvasPos)
{
if(lastCanvasPos == Vector2.zero)
{
DrawBrush(canvasPos, currentColor);
}
else
{
int lerpNum = (int)Vector3.Distance(canvasPos, lastCanvasPos);
for(int i = 0; i <= lerpNum; i++)
{
float lerpPos = Mathf.InverseLerp(0, lerpNum, i);
Vector2 lerpedCanvasPos = Vector2.Lerp(canvasPos, lastCanvasPos, lerpPos);
DrawBrush(lerpedCanvasPos, currentColor);
}
}
lastCanvasPos = canvasPos;
}
private void DrawBrush(Vector2 brushPos, Color brushColor)
{
int brushRigth = Mathf.RoundToInt(brushPos.x - (brushSize * 0.5f));
int brushTop = Mathf.RoundToInt(brushPos.y - (brushSize * 0.5f));
for(int ix = brushRigth; ix < brushRigth + (int)brushSize; ix++)
{
for(int iy = brushTop; iy < brushTop + (int)brushSize; iy++)
{
if(ix >= 0 && ix < canvasSizeX) // Check if we are within the canvas
{
if(iy >= 0 && iy < canvasSizeY)
{
float brushCenterDistance = (brushPos - new Vector2(ix, iy)).magnitude; // Calculate the distance from the center of the brush
float colorLerp = Mathf.InverseLerp((int)brushSize * 0.5f, 0.0f, brushCenterDistance);
pixelColorArray[ix, iy] = Color.Lerp((pixelColorArray[ix, iy]), brushColor, colorLerp * brushColor.a); // Lerp the color towards the brush color based on the distance from the center of the brush
}
}
}
}
}
The code works by manipulating a 2D color array which is later later applied to a texture.
The “Draw” function is called each update with the current position of the mouse/touch on the canvas.
The “Draw” function then calls the “DrawBrush” function on each pixel point between the current position of the touch and the position of the previous update. The “DrawBrush” functions lerps the color at the position its given and nearby points towards the brush color, based on that’s point distance from the center of the brush.
As you can see, this isn’t very efficient. If the brush size is 20, then at each point in a brush stroke a 20*20 square of color objects is lerped towards the brush color. Causing the color points accessed by the brush, to be lerped many times in a single brush stroke. Because the brush areas overlap.
I think i have thought of a way to optimize this. By calling the “DrawBrush” function at the start and the end of a brush stroke. Then have a BrushSweep function that basically functions by making a single pixel wide line from start to end that is lerped fully towards the brush color. And then have the pixels outside the line be gradually lerped less and less towards the brush color based on distance from the line.
Making this work for straight lines would be easy. Problem is that i am not quite sure how to make this work for brush strokes that are at a angle. Anyone got a suggestion on how to achieve this?
Or do someone have a idea for another way to do this that don’t access each color object more than one time?
Pleas let me know if i have not explained my problem sufficiently, and i will try to provide more detail.