上一篇中,SetPixel的方法,卡顿严重,暂未解决,又去看了原来的GL画线,自己画图思考了一下适配UI的问题,最终解决。
特此说明,GL画线功能,及Shader均为借鉴,自己做了优化。
程序代码如下:
(MouseOverController.GetOverUI(UIManager.GetInstance().GetCanvas().gameObject) == null 这句为UI判断)
/************************************************************Copyright (C), 2007-2016,BJ Rainier Tech. Co., Ltd.FileName: Painting.csAuthor:末零 Version :1.0 Date: 2018-11-10Description:画图功能
************************************************************/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;//接收图的RenderTextureprivate Material mat;//材质球private RawImage rImage;//RawImage,自身private RectTransform rTransform;//RectTransformprivate 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();}}/// <summary>/// 初始化设置/// </summary>public void SetPainting(){rTransform = GetComponent<RectTransform>();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<RawImage>();Debug.Log(rImage);rImage.texture = texRender;}/// <summary>/// 开始画线/// </summary>/// <param name="pos"></param>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;}/// <summary>/// 结束画线/// </summary>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();}/// <summary>/// 重置RenderTexture/// </summary>/// <param name="destTexture"></param>private void Clear(RenderTexture destTexture){Graphics.SetRenderTarget(destTexture);GL.PushMatrix();GL.Clear(true, true, Color.white);GL.PopMatrix();}/// <summary>/// 外部可以调用的重置修改的RenderTexture/// </summary>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 OffLighting OffZWrite OffFog{ Mode Off }Blend One OneMinusSrcAlphaPass{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下载