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);
|
||
}
|
||
}
|