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