上一篇中,SetPixel的方法,卡顿严重,暂未解决,又去看了原来的GL画线,自己画图思考了一下适配UI的问题,最终解决。
特此说明,GL画线功能,及Shader均为借鉴,自己做了优化。
程序代码如下:
(MouseOverController.GetOverUI(UIManager.GetInstance().GetCanvas().gameObject) == null 这句为UI判断)
/************************************************************
Copyright (C), 2007-2016,BJ Rainier Tech. Co., Ltd.
FileName: Painting.cs
Author:末零 Version :1.0 Date: 2018-11-10
Description:画图功能
************************************************************/
using UnityEngine;
using UnityEngine.UI;
namespace LastZero.Utility
{
public class Painting : MonoBehaviour
{
public Color mColor = Color.black;//画笔颜色
[HideInInspector]
public Texture brushTexture;//画笔
[HideInInspector]
public float brushScale = 0.1f;//画笔大小
[HideInInspector]
public bool isEraser = false;//是否使用橡皮擦
private RenderTexture texRender;//接收图的RenderTexture
private Material mat;//材质球
private RawImage rImage;//RawImage,自身
private RectTransform rTransform;//RectTransform
private Vector3 startPosition = Vector3.zero;
private Vector3 endPosition = Vector3.zero;
private Vector2 posOffset;
private void Start()
{
SetPainting();
posOffset.Set((Screen.width - rTransform.sizeDelta.x * transform.root.localScale.x) / 2 + transform.position.x - transform.root.position.x, (Screen.height - rTransform.sizeDelta.y * transform.root.localScale.y) / 2 + transform.position.y - transform.root.position.y);
}
void Update()
{
if (MouseOverController.GetOverUI(transform.root.gameObject) == null)
{
EndPainting();
return;
}
else if (MouseOverController.GetOverUI(transform.root.gameObject).name != gameObject.name)
{
EndPainting();
return;
}
if (Input.GetMouseButton(0))
{
StartPainting(new Vector3(Input.mousePosition.x - posOffset.x, Input.mousePosition.y - posOffset.y, 0));
}
if (Input.GetMouseButtonUp(0))
{
EndPainting();
}
}
///
/// 初始化设置
///
public void SetPainting()
{
rTransform = GetComponent();
mat = new Material(Shader.Find("Custom/Painting"));
texRender = new RenderTexture((int)rTransform.sizeDelta.x, (int)rTransform.sizeDelta.y, 24, RenderTextureFormat.ARGB32);
Clear(texRender);
rImage = GetComponent();
Debug.Log(rImage);
rImage.texture = texRender;
}
///
/// 开始画线
///
///
public void StartPainting(Vector3 pos)
{
endPosition = pos;
if (startPosition.Equals(Vector3.zero))
{
startPosition = endPosition;
return;
}
float distance = Vector3.Distance(startPosition, endPosition);
if (distance > 1)
{
int d = (int)distance;
for (int i = 0; i < d; i++)
{
float difx = endPosition.x - startPosition.x;
float dify = endPosition.y - startPosition.y;
float delta = (float)i / distance;
if (isEraser)
{
DrawBrush(texRender, new Vector2(startPosition.x + (difx * delta), startPosition.y + (dify * delta)), brushTexture, Color.white, brushScale);
}
else
{
DrawBrush(texRender, new Vector2(startPosition.x + (difx * delta), startPosition.y + (dify * delta)), brushTexture, mColor, brushScale);
}
}
}
startPosition = endPosition;
}
///
/// 结束画线
///
public void EndPainting()
{
startPosition = Vector3.zero;
}
private void DrawBrush(RenderTexture destTexture, Vector2 pos, Texture sourceTexture, Color color, float scale)
{
DrawBrush(destTexture, (int)pos.x, (int)pos.y, sourceTexture, color, scale);
}
private void DrawBrush(RenderTexture destTexture, int x, int y, Texture sourceTexture, Color color, float scale)
{
DrawBrush(destTexture, new Rect(x, y, sourceTexture.width, sourceTexture.height), sourceTexture, color, scale);
}
private void DrawBrush(RenderTexture destTexture, Rect destRect, Texture sourceTexture, Color color, float scale)
{
Graphics.SetRenderTarget(destTexture);
float left = destRect.xMin - destRect.width * scale / 2.0f;
float right = destRect.xMin + destRect.width * scale / 2.0f;
float top = destRect.yMin - destRect.height * scale / 2.0f;
float bottom = destRect.yMin + destRect.height * scale / 2.0f;
GL.PushMatrix();
GL.LoadOrtho();
mat.SetTexture("_MainTex", brushTexture);
mat.SetColor("_Color", color);
mat.SetPass(0);
GL.Begin(GL.QUADS);
GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(left / (int)rTransform.sizeDelta.x / transform.root.localScale.x, top / (int)rTransform.sizeDelta.y / transform.root.localScale.y, 0);
GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(right / (int)rTransform.sizeDelta.x / transform.root.localScale.x, top / (int)rTransform.sizeDelta.y / transform.root.localScale.y, 0);
GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(right / (int)rTransform.sizeDelta.x / transform.root.localScale.x, bottom / (int)rTransform.sizeDelta.y / transform.root.localScale.y, 0);
GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(left / (int)rTransform.sizeDelta.x / transform.root.localScale.x, bottom / (int)rTransform.sizeDelta.y / transform.root.localScale.y, 0);
GL.End();
GL.PopMatrix();
}
///
/// 重置RenderTexture
///
///
private void Clear(RenderTexture destTexture)
{
Graphics.SetRenderTarget(destTexture);
GL.PushMatrix();
GL.Clear(true, true, Color.white);
GL.PopMatrix();
}
///
/// 外部可以调用的重置修改的RenderTexture
///
public void ClearAll()
{
Clear(texRender);
}
}
}
Shader:
Shader "Custom/Painting"
{
Properties
{
_MainTex("MainTex (RGB) Trans (A)", 2D) = "white" {}
_Color("Color", Color) = (1,1,1,1)
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"IgnoreProjector" = "True"
"RenderType" = "Transparent"
"PreviewType" = "Plane"
"CanUseSpriteAtlas" = "True"
}
Cull Off
Lighting Off
ZWrite Off
Fog{ Mode Off }
Blend One OneMinusSrcAlpha
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 vertex : SV_POSITION;
half2 texcoord : TEXCOORD0;
};
fixed4 _Color;
v2f vert(appdata_base IN)
{
v2f OUT;
OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
OUT.texcoord = IN.texcoord;
return OUT;
}
sampler2D _MainTex;
fixed4 frag(v2f IN) : SV_Target
{
float4 col = _Color * tex2D(_MainTex, IN.texcoord);
col.rgb *= col.a;
return col;
}
ENDCG
}
}
}
效果图:
需要Demo可移步下载:
Demo下载