116 lines
3.3 KiB
C#
116 lines
3.3 KiB
C#
|
|
using UnityEngine;
|
|||
|
|
using UnityEngine.UI;
|
|||
|
|
|
|||
|
|
public class ScratchMask : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
public RawImage maskImage; // 黑白图
|
|||
|
|
public Texture2D brushTex; // 笔刷纹理
|
|||
|
|
Camera uiCamera; // Canvas 摄像机
|
|||
|
|
public int rtResolution = 1024; // 遮罩精度
|
|||
|
|
private Texture2D readTex; // 遮罩纹理
|
|||
|
|
bool HasRevealed = false;
|
|||
|
|
public float revealThreshold = 0.8f; // 擦除面积阈值 (30%)
|
|||
|
|
|
|||
|
|
private RenderTexture maskRT;
|
|||
|
|
private Material mat;
|
|||
|
|
|
|||
|
|
void Start()
|
|||
|
|
{
|
|||
|
|
// 创建遮罩 RT
|
|||
|
|
maskRT = new RenderTexture(rtResolution, rtResolution, 0);
|
|||
|
|
maskRT.Create();
|
|||
|
|
uiCamera = Camera.main;
|
|||
|
|
// 填满为白色(遮罩默认不透明)
|
|||
|
|
RenderTexture.active = maskRT;
|
|||
|
|
GL.Clear(true, true, Color.white);
|
|||
|
|
RenderTexture.active = null;
|
|||
|
|
|
|||
|
|
// 获取材质并设置遮罩纹理
|
|||
|
|
mat = maskImage.material;
|
|||
|
|
mat.SetTexture("_MaskTex", maskRT);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void Update()
|
|||
|
|
{
|
|||
|
|
if (Input.GetMouseButton(0))
|
|||
|
|
{
|
|||
|
|
Vector2 localPos;
|
|||
|
|
RectTransformUtility.ScreenPointToLocalPointInRectangle(
|
|||
|
|
maskImage.rectTransform,
|
|||
|
|
Input.mousePosition,
|
|||
|
|
uiCamera,
|
|||
|
|
out localPos
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
Vector2 uv = new Vector2(
|
|||
|
|
(localPos.x + maskImage.rectTransform.rect.width / 2) / maskImage.rectTransform.rect.width,
|
|||
|
|
(localPos.y + maskImage.rectTransform.rect.height / 2) / maskImage.rectTransform.rect.height
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
DrawBrush(uv);
|
|||
|
|
CheckRevealProgress();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void DrawBrush(Vector2 uv)
|
|||
|
|
{
|
|||
|
|
// int px = (int)(uv.x * maskRT.width);
|
|||
|
|
// int py = (int)(uv.y * maskRT.height);
|
|||
|
|
int px = (int)(uv.x * maskRT.width);
|
|||
|
|
// 反转 Y:
|
|||
|
|
int py = maskRT.height - (int)(uv.y * maskRT.height);
|
|||
|
|
|
|||
|
|
RenderTexture.active = maskRT;
|
|||
|
|
GL.PushMatrix();
|
|||
|
|
GL.LoadPixelMatrix(0, maskRT.width, maskRT.height, 0);
|
|||
|
|
// GL.LoadPixelMatrix(0, maskRT.width, 0, maskRT.height);
|
|||
|
|
|
|||
|
|
Graphics.DrawTexture(
|
|||
|
|
new Rect(px - brushTex.width / 2, py - brushTex.height / 2, brushTex.width, brushTex.height),
|
|||
|
|
brushTex
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
GL.PopMatrix();
|
|||
|
|
RenderTexture.active = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void CheckRevealProgress()
|
|||
|
|
{
|
|||
|
|
if (HasRevealed) return;
|
|||
|
|
|
|||
|
|
RenderTexture.active = maskRT;
|
|||
|
|
|
|||
|
|
if (readTex == null)
|
|||
|
|
readTex = new Texture2D(maskRT.width, maskRT.height, TextureFormat.RGB24, false);
|
|||
|
|
|
|||
|
|
readTex.ReadPixels(new Rect(0, 0, maskRT.width, maskRT.height), 0, 0);
|
|||
|
|
readTex.Apply();
|
|||
|
|
|
|||
|
|
int clearCount = 0;
|
|||
|
|
Color[] pixels = readTex.GetPixels();
|
|||
|
|
|
|||
|
|
foreach (var pixel in pixels)
|
|||
|
|
{
|
|||
|
|
if (pixel.r < 0.5f) // 黑色(已擦除)
|
|||
|
|
clearCount++;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
float percent = clearCount / (float)pixels.Length;
|
|||
|
|
|
|||
|
|
if (percent > revealThreshold)
|
|||
|
|
{
|
|||
|
|
Debug.Log("✔️ 已擦除足够区域,显示彩色图!");
|
|||
|
|
RevealColorImage();
|
|||
|
|
HasRevealed = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
RenderTexture.active = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void RevealColorImage()
|
|||
|
|
{
|
|||
|
|
maskImage.gameObject.SetActive(false); // 隐藏黑白图
|
|||
|
|
// 或者:maskImage.color = new Color(1,1,1,0);
|
|||
|
|
}
|
|||
|
|
}
|