solution 1
very similar to your solution 1, but use blend formula:
final color = base color * (1 - brush alpha) + brush pixel * brush alpha
and you needn’t to store any previous actions
solution 2
just place a transparent planes (each is 4 vertices + 2 triangles) with texture of brush and color customized in material. shader should be additive or simple transparent, depends on your task. so background is static image, and at front of it a set of planes that placed in brush way. using scale and alpha you can customize size/power of brush. color is color as is. in performance reason you can do something like 'bake drawing', that will take a brushed image and place it as background with removing all drawed planes.
edit:
http://zammyart.com/UA/Painter/WebPlayer.html
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class UnbreakablePaint : MonoBehaviour
{
public Transform BrushPrefab;
public Material MaterialForPrefab;
public Material MaterialForDrawPlane;
public Camera BakeCamera;
public RenderTexture TextureUsedInBakeCamera;
float betweenPointDistance = 0.1f;
Vector3 lastBrushPosition = Vector3.zero;
bool lastBrushExists = false;
Material currentMaterial;
Color materialColor = Color.black;
List brushesToDelete;
void OnGUI()
{
GUI.Label(new Rect(10f, 10f, 10f, 30f), "R");
GUI.Label(new Rect(10f, 40f, 10f, 30f), "G");
GUI.Label(new Rect(10f, 70f, 10f, 30f), "B");
GUI.Label(new Rect(10f, 100f, 10f, 30f), "A");
materialColor.r = GUI.HorizontalSlider(new Rect(30f, 10f, 100f, 30f), materialColor.r, 0f, 1f);
materialColor.g = GUI.HorizontalSlider(new Rect(30f, 40f, 100f, 30f), materialColor.g, 0f, 1f);
materialColor.b = GUI.HorizontalSlider(new Rect(30f, 70f, 100f, 30f), materialColor.b, 0f, 1f);
materialColor.a = GUI.HorizontalSlider(new Rect(30f, 100f, 100f, 30f), materialColor.a, 0f, 1f);
GUI.Label(new Rect(10f, Screen.height - 40f, 400f, 30f), "select color and draw with right mouse button");
}
void Update()
{
if (Input.GetMouseButtonDown(1))
{
currentMaterial = new Material(MaterialForPrefab);
currentMaterial.color = materialColor;
brushesToDelete = new List();
}
if (Input.GetMouseButton(1))
{
Ray mouseRay = Camera.main.ScreenPointToRay(Input.mousePosition);
Vector3 newBrushPosition = mouseRay.origin - mouseRay.direction / mouseRay.direction.y * mouseRay.origin.y;
while (!lastBrushExists || (newBrushPosition - lastBrushPosition).sqrMagnitude >= betweenPointDistance * betweenPointDistance)
{
MakePaint(newBrushPosition);
}
}
if (Input.GetMouseButtonUp(1))
{
lastBrushExists = false;
BakeCamera.Render();
RenderTexture.active = TextureUsedInBakeCamera;
Texture2D tex2d = new Texture2D(TextureUsedInBakeCamera.width, TextureUsedInBakeCamera.height, TextureFormat.RGB24, false);
tex2d.ReadPixels(new Rect(0, 0, TextureUsedInBakeCamera.width, TextureUsedInBakeCamera.height), 0, 0);
tex2d.Apply();
MaterialForDrawPlane.mainTexture = tex2d;
for (int i = brushesToDelete.Count - 1; i >= 0; i--)
{
Destroy(brushesToDelete*.gameObject);*
* }*
* }*
* }*
* void MakePaint(Vector3 pointPaintDirectionTo)*
* {*
* Vector3 pointPaintNow = lastBrushExists ? Vector3.MoveTowards(lastBrushPosition, pointPaintDirectionTo, betweenPointDistance) : pointPaintDirectionTo;*
* Transform brush = Instantiate(BrushPrefab, pointPaintNow, Quaternion.identity) as Transform;*
* brushesToDelete.Add(brush);*
* brush.renderer.material = currentMaterial;*
* lastBrushPosition = pointPaintNow;*
* lastBrushExists = true;*
* }*
*}*
*
*