// DrawOn3D.cs using UnityEngine; /// /// 在3D模型上涂鸦 /// public class DrawOn3D : MonoBehaviour { Texture2D tex; float[,] floats; int width = 1024; int height = 1024; private void Start() { MeshRenderer mr = GetComponent(); Material mat = mr.materials[0]; //var texture = mat.mainTexture; //RenderTexture tempRT = RenderTexture.GetTemporary(texture.width, texture.height, 0, RenderTextureFormat.Default, RenderTextureReadWrite.Linear); //Graphics.Blit(texture, tempRT); //RenderTexture previous = RenderTexture.active; //RenderTexture.active = tempRT; //tex = new Texture2D(texture.width, texture.height); //tex.ReadPixels(new Rect(0, 0, texture.width, texture.height), 0, 0); //tex.Apply(); //RenderTexture.active = previous; //RenderTexture.ReleaseTemporary(tempRT); floats = new float[width, height]; tex = new Texture2D(width, height, TextureFormat.ARGB32, false); mat.SetTexture("_MaskTex", tex); var painColor = new Color(0, 0, 0, 0); for (int i = 0; i < tex.width; i++) { for (int j = 0; j < tex.height; j++) { tex.SetPixel(i, j, painColor); } } tex.Apply(); } int R = 80; //默认半径 int defaultR = 80; bool isDrawing = false; public bool isEraser = true; float lastTime = 0; Vector3 lastPos; Vector3 curPos; private void Update() { if (Input.GetMouseButtonDown(0)) { isDrawing = true; R = defaultR; lastTime = 0; lastPos = Input.mousePosition; curPos = Input.mousePosition; } else if (Input.GetMouseButtonUp(0)) { isDrawing = false; R = defaultR; lastTime = 0; } if (isDrawing) { lastTime += Time.deltaTime; lastPos = Input.mousePosition; if (lastTime > 0.05f) { lastTime = 0; curPos = Input.mousePosition; if (Vector2.Distance(lastPos, curPos) > 1) { R = defaultR; lastPos = curPos; } else { R += 10; } Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { Vector2 pixelUV = hit.textureCoord; pixelUV.x *= tex.width; pixelUV.y *= tex.height; //var painColor = tex.GetPixel((int)pixelUV.x, (int)pixelUV.y); //painColor.a = 0; drawCircleAt((int)pixelUV.x, (int)pixelUV.y, Color.white); } } } } void drawCircleAt(int x, int y, Color color) { if (isEraser) { for (int i = x - R; i < x + R; i++) { if (i >= 0 && i < width) { for (int j = y - R; j < y + R; j++) { if (j >= 0 && j < height && floats[i, j] >= 0) { float distance = Vector2.Distance(new Vector2(i, j), new Vector2(x, y)); if (distance <= R) { floats[i, j] -= 1 - distance / R; tex.SetPixel(i, j, color * (1 - floats[i, j])); } } } } } } else { for (int i = x - R; i < x + R; i++) { if (i >= 0 && i < width) { for (int j = y - R; j < y + R; j++) { if (j >= 0 && j < height && floats[i, j] <= 1) { float distance = Vector2.Distance(new Vector2(i, j), new Vector2(x, y)); if (distance <= R) { floats[i, j] += 1 - distance / R; tex.SetPixel(i, j, color * (1 - floats[i, j])); } } } } } } tex.Apply(); } }