150 lines
4.5 KiB
C#
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();
|
|
}
|
|
}
|