Files
MinFt/Client/Assets/AssetsPackage/art/ship/Garage/Test/DrawOn3D.cs
2026-04-27 12:07:32 +08:00

150 lines
4.5 KiB
C#

// DrawOn3D.cs
using UnityEngine;
/// <summary>
/// 在3D模型上涂鸦
/// </summary>
public class DrawOn3D : MonoBehaviour
{
Texture2D tex;
float[,] floats;
int width = 1024;
int height = 1024;
private void Start()
{
MeshRenderer mr = GetComponent<MeshRenderer>();
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();
}
}