Unity画线之GL

上一篇中,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
	}
	}
}

效果图:

Unity画线之GL_第1张图片

需要Demo可移步下载:

Demo下载

你可能感兴趣的:(Unity3D)