Files
aibis-dream/Assets/Scripts/FixSystem/Memory/MemoryPainter.cs
T
2024-10-10 12:46:34 +08:00

160 lines
5.1 KiB
C#

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
public class MemoryPainter : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler
{
public Material MemoryMaterial; // 材质
private RenderTexture MaskTexture; // 遮罩纹理
public Texture2D BrushTexture; // 画笔纹理
public float BrushSize = 50f; // 画笔大小
public Camera UICamera; // 用于屏幕坐标到世界坐标转换
public Material BlurMaterial; // 模糊材质
public float BlurSize = 1.0f; // 模糊程度
private bool isDrawing = false;
private bool needsBlur = false;
private float blurTimer = 0f;
private float blurInterval = 0.02f; // 模糊处理的时间间隔
private RectTransform rectTransform;
private RawImage rawImage;
private Material brushMaterial;
private void Start()
{
// 初始化
rectTransform = GetComponent<RectTransform>();
rawImage = GetComponent<RawImage>();
MaskTexture = new RenderTexture(1920, 1080, 0, RenderTextureFormat.ARGB32);
// 将遮罩纹理赋给材质
MemoryMaterial.SetTexture("_MaskTexture", MaskTexture);
// 初始化遮罩纹理
InitRenderTexture();
// 设置材质到 RawImage
rawImage.material = MemoryMaterial;
// 创建笔刷材质
brushMaterial = new Material(Shader.Find("Unlit/Transparent"));
brushMaterial.mainTexture = BrushTexture;
brushMaterial.color = new Color(1, 1, 1, 0.3f); // 半透明,Alpha 值为 0.1
// 设置笔刷材质的混合模式为加法混合
brushMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
//brushMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
brushMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.One);
brushMaterial.SetInt("_BlendOp", (int)UnityEngine.Rendering.BlendOp.Add);
brushMaterial.renderQueue = 3000;
}
private void InitRenderTexture()
{
RenderTexture currentRT = RenderTexture.active;
RenderTexture.active = MaskTexture;
GL.Clear(true, true, Color.black); // 全黑表示未上色区域
RenderTexture.active = currentRT;
}
public void OnPointerDown(PointerEventData eventData)
{
isDrawing = true;
needsBlur = true; // 开启模糊处理
Draw(eventData);
}
public void OnPointerUp(PointerEventData eventData)
{
isDrawing = false;
// 一段时间后停止模糊处理
StartCoroutine(StopBlurAfterDelay(2.0f));
}
private IEnumerator StopBlurAfterDelay(float delay)
{
yield return new WaitForSeconds(delay);
needsBlur = false;
}
public void OnDrag(PointerEventData eventData)
{
if (isDrawing)
{
Draw(eventData);
}
}
private void Draw(PointerEventData eventData)
{
Vector2 localPoint;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, eventData.position, UICamera, out localPoint))
{
// 将本地坐标转换为 UV 坐标
float uvX = (localPoint.x - rectTransform.rect.x) / rectTransform.rect.width;
float uvY = (localPoint.y - rectTransform.rect.y) / rectTransform.rect.height;
// 绘制到遮罩纹理
DrawAt(uvX, uvY);
}
}
private void DrawAt(float uvX, float uvY)
{
RenderTexture currentRT = RenderTexture.active;
RenderTexture.active = MaskTexture;
GL.PushMatrix();
GL.LoadPixelMatrix(0, MaskTexture.width, MaskTexture.height, 0);
// 设置绘制位置和大小
float x = uvX * MaskTexture.width - (BrushSize / 2);
float y = (1 - uvY) * MaskTexture.height - (BrushSize / 2);
// 绘制多次,位置略有偏移,模拟扩散
int iterations = 5; // 您可以根据需要调整迭代次数
float spread = 1.0f; // 扩散范围
for (int i = 0; i < iterations; i++)
{
float offsetX = Random.Range(-spread, spread);
float offsetY = Random.Range(-spread, spread);
Graphics.DrawTexture(new Rect(x + offsetX, y + offsetY, BrushSize, BrushSize), BrushTexture, brushMaterial);
}
GL.PopMatrix();
RenderTexture.active = currentRT;
}
private void Update()
{
if (needsBlur)
{
blurTimer += Time.deltaTime;
if (blurTimer >= blurInterval)
{
ApplyBlurToMaskTexture();
blurTimer = 0f;
}
}
}
private void ApplyBlurToMaskTexture()
{
// 设置模糊程度
BlurMaterial.SetFloat("_BlurSize", BlurSize);
// 创建一个临时的 RenderTexture
RenderTexture tempRT = RenderTexture.GetTemporary(MaskTexture.width, MaskTexture.height, 0, MaskTexture.format);
// 使用模糊材质处理遮罩纹理
Graphics.Blit(MaskTexture, tempRT, BlurMaterial);
// 将模糊后的结果拷贝回遮罩纹理
Graphics.Blit(tempRT, MaskTexture);
RenderTexture.ReleaseTemporary(tempRT);
}
}