Unity画线之SetPixel

之前简单看过一下GL画线,由于适配问题,未能实现,后面有时间在看一下具体原因,今天以重绘像素的方式实现了画线,由于算法不好,会有卡顿,后面会继续优化。

这个画线功能,是以RawImage实现的。

首先获取RawImage和RectTransform:

rawImage = GetComponent();
rectTransform = rawImage.GetComponent();      

然后进行RawImage的初始化:

Vector3 pos = rectTransform.position ;
texture = new Texture2D((int)rectTransform.sizeDelta.x, (int)rectTransform.sizeDelta.y);
Clear();
rawImage.texture = texture;

public void Clear()
{
    int x, y;
    for (x = 0; x < texture.width; x++)
    {
        for (y = 0; y < texture.height; y++)
        {
            texture.SetPixel(x, y, Color.white);
        }
     }
     texture.Apply();
}

获取偏移量:

Vector3 posOffset3d = transform.position - transform.root.position;
posOffset = new Vector2(posOffset3d.x + (Screen.width - rectTransform.sizeDelta.x) / 2, posOffset3d.y + (Screen.height - rectTransform.sizeDelta.y) / 2);

下面进行绘制:

private void Draw(Vector2 position, int sideLength)
{
    int x, y;
    for (y = 0 - sideLength; y < sideLength; y++)
    {
        for (x = 0 - sideLength; x < sideLength; x++)
        {
            if (isEraser == true)
            {
                texture.SetPixel((int)position.x - x, (int)position.y - y, Color.white);
            }
            else
            {
                texture.SetPixel((int)position.x - x, (int)position.y - y, brushColor);
            }
        }
    }
    texture.Apply();
}
private void DrawLerp(Vector2 pos)
{
    if (isBegin == false)
    {
        isBegin = true;
        previousPosition = pos;
    }
    distance.Set(pos.x - previousPosition.x, pos.y - previousPosition.y);
    float length = Mathf.Sqrt(distance.x * distance.x + distance.y * distance.y);
    int interval = brushSize < 2 ? 1 : brushSize / 2;
    int num = (int)length / interval;

    float d_x = (distance.x / num);
    float d_y = (distance.y / num);
    float p_x = (previousPosition.x);
    float p_y = (previousPosition.y);

    if (length > interval)
    {
        for (int i = 1; i < num; i++)
        {
            float v_x = p_x + d_x * i;
            float v_y = p_y + d_y * i;
            Draw(new Vector2(v_x, v_y), brushSize);
        }
    }
    else
    {
        Draw(pos, brushSize);
    }
    previousPosition = pos;
}

完整代码如下(触发判断为自己写的功能):

using UnityEngine;
using UnityEngine.UI;

using LastZero.Event;

namespace LastZero
{
    public class Drawing: MonoBehaviour {

        public Color brushColor;//画笔颜色
        public int brushSize = 1;//画笔宽度

        private RawImage rawImage;//画图所用图片
        private RectTransform rectTransform;//RrectTransform
        private Texture2D texture;//贴图
        private Color colorBackGround;//背景色
        private bool isCanDraw;//是否可以画图
        private Vector2 posOffset;//偏移
        private bool isEraser;//是否使用橡皮擦

        private bool isBegin = false;//是否开始
        private Vector2 previousPosition;//旧坐标
        private Vector2 distance;//新旧点的距离

        private void Awake()
        {
            rawImage = GetComponent();
            rectTransform = rawImage.GetComponent();       
        }

        private void Start()
        {
            RawImageInit();
            colorBackGround = rawImage.color;
            isCanDraw = false;

            Setoffset();

            DrawController();
        }

        /// 
        /// RawImage初始化
        /// 
        private void RawImageInit()
        {
            Vector3 pos = rectTransform.position ;
            texture = new Texture2D((int)rectTransform.sizeDelta.x, (int)rectTransform.sizeDelta.y);
            Clear();
            rawImage.texture = texture;
        }

        private void Setoffset()
        {
            Vector3 posOffset3d = transform.position - transform.root.position;
            posOffset = new Vector2(posOffset3d.x + (Screen.width - rectTransform.sizeDelta.x) / 2, posOffset3d.y + (Screen.height - rectTransform.sizeDelta.y) / 2);
        }

        /// 
        /// 清空
        /// 
        public void Clear()
        {
            int x, y;
            for (x = 0; x < texture.width; x++)
            {
                for (y = 0; y < texture.height; y++)
                {
                    texture.SetPixel(x, y, Color.white);
                }
            }
            texture.Apply();
        }

        /// 
        /// 绘制控制
        /// 
        private void DrawController()
        {
            Vector2 pos = new Vector2();
            gameObject.AddEnterEvent(delegate {
                isCanDraw = true;
            });
            gameObject.AddExitEvent(delegate {
                isCanDraw = false;
                isBegin = false;
            });
            gameObject.AddDrugEvent(delegate
            {
                if (!isCanDraw)
                    return;

                pos.Set(Input.mousePosition.x - posOffset.x, Input.mousePosition.y - posOffset.y);
                DrawLerp(pos);
            });
            gameObject.AddEndDrugEvent(delegate
            {
                isBegin = false;
            });
        }

        /// 
        /// 方形
        /// 
        /// 
        /// 
        private void Draw(Vector2 position, int sideLength)
        {
            int x, y;
            for (y = 0 - sideLength; y < sideLength; y++)
            {
                for (x = 0 - sideLength; x < sideLength; x++)
                {
                    if (isEraser == true)
                    {
                        texture.SetPixel((int)position.x - x, (int)position.y - y, Color.white);
                    }
                    else
                    {
                        texture.SetPixel((int)position.x - x, (int)position.y - y, brushColor);
                    }
                }
            }
            texture.Apply();
        }


        private void DrawLerp(Vector2 pos)
        {
            if (isBegin == false)
            {
                isBegin = true;
                previousPosition = pos;
            }  
            distance.Set(pos.x - previousPosition.x, pos.y - previousPosition.y);
            float length = Mathf.Sqrt(distance.x * distance.x + distance.y * distance.y);
            int interval = brushSize < 2 ? 1 : brushSize / 2;
            int num = (int)length / interval;//将间距切割成固定片段,并在每个片段打点
            
            float d_x = (distance.x / num);
            float d_y = (distance.y / num);
            float p_x = (previousPosition.x);
            float p_y = (previousPosition.y);

            if (length > interval)
            {
                for (int i = 1; i < num; i++)
                {
                    float v_x = p_x + d_x * i;
                    float v_y = p_y + d_y * i;
                    Draw(new Vector2(v_x, v_y), brushSize);
                }
            }
            else
            {
                Draw(pos, brushSize);
            }
            previousPosition = pos;
        }
    }
}

 

你可能感兴趣的:(Unity3D,Unity,画线,SetPixel)