查看: 942|回复: 0
打印 上一主题 下一主题

[其他] unity UI写字效果的代码

[复制链接]
may    

8830

主题

80

听众

7万

积分

首席设计师

Rank: 8Rank: 8

纳金币
52304
精华
343

最佳新人 热心会员 灌水之王 活跃会员 突出贡献 荣誉管理 论坛元老

跳转到指定楼层
楼主
发表于 2019-8-29 11:35:15 |只看该作者 |倒序浏览
来自:1320494699
  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. using Random = UnityEngine.Random;

  4. public class Painting : MonoBehaviour
  5. {

  6.     private RenderTexture texRender;   //画布
  7.     public Material mat;     //给定的shader新建材质
  8.     public Texture brushTypeTexture;   //画笔纹理,半透明
  9.     private Camera mainCamera;
  10.     public float brushScale = 0.5f;
  11.     public float _rate = 0.5f;
  12.     public Color brushColor = Color.black;
  13.     public RawImage raw;                   //使用UGUI的RawImage显示,方便进行添加UI,将pivot设为(0.5,0.5)
  14.     private float lastDistance;
  15.     private Vector3[] PositionArray = new Vector3[3];
  16.     private int a = 0;
  17.     private Vector3[] PositionArray1 = new Vector3[4];
  18.     private int b = 0;
  19.     private float[] speedArray = new float[4];
  20.     private int s = 0;
  21.     public int num = 50;

  22.     Vector2 rawMousePosition;            //raw图片的左下角对应鼠标位置
  23.     float rawWidth;                               //raw图片宽度
  24.     float rawHeight;   
  25.     //raw图片长度

  26.     public bool isPainting = true;
  27.     void Start()
  28.     {

  29.         //raw图片鼠标位置,宽度计算
  30.         rawWidth = raw.rectTransform.sizeDelta.x;
  31.         rawHeight = raw.rectTransform.sizeDelta.y;
  32.         Vector2 rawanchorPositon = new Vector2(raw.rectTransform.anchoredPosition.x - raw.rectTransform.sizeDelta.x / 2.0f, raw.rectTransform.anchoredPosition.y - raw.rectTransform.sizeDelta.y / 2.0f);
  33.         rawMousePosition = rawanchorPositon + new Vector2(Screen.width / 2.0f, Screen.height / 2.0f);

  34.         //texRender = new RenderTexture(1000, 1000, 24, RenderTextureFormat.ARGB32);
  35.         texRender = new RenderTexture((int)raw.rectTransform.rect .width, (int)raw.rectTransform.rect.height, 24, RenderTextureFormat.ARGB32);
  36.         Clear(texRender);
  37.     }

  38.     Vector3 startPosition = Vector3.zero;
  39.     Vector3 endPosition = Vector3.zero;
  40.     void Update()
  41.     {
  42.         if (!isPainting)
  43.         {
  44.             OnMouseUp();
  45.         }
  46.         else
  47.         {
  48.             if (Input.GetMouseButton(0)||Input.touchCount>0&&Input.GetTouch(0).phase==TouchPhase.Moved)
  49.             {
  50.                 OnMouseMove(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0));
  51.             }
  52.             if (Input.GetMouseButtonUp(0) || Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Ended)
  53.             {
  54.                 OnMouseUp();
  55.             }
  56.             DrawImage();
  57.         }
  58.     }

  59.     void OnMouseUp()
  60.     {
  61.         startPosition = Vector3.zero;
  62.         //brushScale = 0.5f;
  63.         a = 0;
  64.         b = 0;
  65.         s = 0;
  66.     }
  67.     //设置画笔宽度
  68.     float SetScale(float distance)
  69.     {
  70.         float Scale = 0;
  71.         if (distance < 100)
  72.         {
  73.             Scale = 0.8f * _rate - 0.005f * distance;
  74.         }
  75.         else
  76.         {
  77.             Scale = 0.425f * _rate - 0.00125f * distance ;
  78.         }
  79.         if (Scale <= 0.05f)
  80.         {
  81.             Scale = 0.05f;
  82.         }
  83.         return Scale;
  84.     }

  85.     void OnMouseMove(Vector3 pos)
  86.     {
  87.         if (startPosition == Vector3.zero)
  88.         {
  89.             startPosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);
  90.         }

  91.         endPosition = pos;
  92.         float distance = Vector3.Distance(startPosition, endPosition);
  93.         brushScale = SetScale(distance);
  94.         ThreeOrderBézierCurse(pos, distance, 1);

  95.         startPosition = endPosition;
  96.         lastDistance = distance;
  97.     }

  98.     void Clear(RenderTexture destTexture)
  99.     {
  100.         Graphics.SetRenderTarget(destTexture);
  101.         GL.PushMatrix();
  102.         GL.Clear(true, true, Color.clear);
  103.         GL.PopMatrix();
  104.     }

  105.     void DrawBrush(RenderTexture destTexture, int x, int y, Texture sourceTexture, Color color, float scale)
  106.     {
  107.         DrawBrush(destTexture, new Rect(x, y, sourceTexture.width, sourceTexture.height), sourceTexture, color, scale);
  108.     }
  109.     void DrawBrush(RenderTexture destTexture, Rect destRect, Texture sourceTexture, Color color, float scale)
  110.     {

  111.         //增加鼠标位置根据raw图片位置换算。
  112.         float left = (destRect.xMin - rawMousePosition.x) * Screen.width / rawWidth - destRect.width * scale / 2.0f;
  113.         float right = (destRect.xMin - rawMousePosition.x) * Screen.width / rawWidth + destRect.width * scale / 2.0f;
  114.         float top = (destRect.yMin - rawMousePosition.y) * Screen.height / rawHeight - destRect.height * scale / 2.0f;
  115.         float bottom = (destRect.yMin - rawMousePosition.y) * Screen.height / rawHeight + destRect.height * scale / 2.0f;

  116.         Graphics.SetRenderTarget(destTexture);

  117.         GL.PushMatrix();
  118.         GL.LoadOrtho();

  119.         mat.SetTexture("_MainTex", brushTypeTexture);
  120.         mat.SetColor("_Color", color);
  121.         mat.SetPass(0);

  122.         GL.Begin(GL.QUADS);

  123.         GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(left / Screen.width, top / Screen.height, 0);
  124.         GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(right / Screen.width, top / Screen.height, 0);
  125.         GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(right / Screen.width, bottom / Screen.height, 0);
  126.         GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(left / Screen.width, bottom / Screen.height, 0);
  127.         //GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(left / 1000, top / 1000, 0);
  128.         //GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(right / 1000, top / 1000, 0);
  129.         //GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(right / 1000, bottom / 1000, 0);
  130.         //GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(left / 1000, bottom / 1000, 0);


  131.         GL.End();
  132.         GL.PopMatrix();
  133.     }
  134.     //bool bshow = true;
  135.     void DrawImage()
  136.     {
  137.         raw.texture = texRender;
  138.     }
  139.     public void OnClickClear()
  140.     {
  141.         Clear(texRender);
  142.     }

  143.     //二阶贝塞尔曲线
  144.     public void TwoOrderBézierCurse(Vector3 pos, float distance)
  145.     {
  146.         PositionArray[a] = pos;
  147.         a++;
  148.         if (a == 3)
  149.         {
  150.             for (int index = 0; index < num; index++)
  151.             {
  152.                 Vector3 middle = (PositionArray[0] + PositionArray[2]) / 2;
  153.                 PositionArray[1] = (PositionArray[1] - middle) / 2 + middle;

  154.                 float t = (1.0f / num) * index / 2;
  155.                 Vector3 target = Mathf.Pow(1 - t, 2) * PositionArray[0] + 2 * (1 - t) * t * PositionArray[1] +
  156.                                  Mathf.Pow(t, 2) * PositionArray[2];
  157.                 float deltaSpeed = (float)(distance - lastDistance) / num;
  158.                 DrawBrush(texRender, (int)target.x, (int)target.y, brushTypeTexture, brushColor, SetScale(lastDistance + (deltaSpeed * index)));
  159.             }
  160.             PositionArray[0] = PositionArray[1];
  161.             PositionArray[1] = PositionArray[2];
  162.             a = 2;
  163.         }
  164.         else
  165.         {
  166.             DrawBrush(texRender, (int)endPosition.x, (int)endPosition.y, brushTypeTexture,
  167.                 brushColor, brushScale);
  168.         }
  169.     }
  170.     //三阶贝塞尔曲线,获取连续4个点坐标,通过调整中间2点坐标,画出部分(我使用了num/1.5实现画出部分曲线)来使曲线平滑;通过速度控制曲线宽度。
  171.     private void ThreeOrderBézierCurse(Vector3 pos, float distance, float targetPosOffset)
  172.     {
  173.         //记录坐标
  174.         PositionArray1[b] = pos;
  175.         b++;
  176.         //记录速度
  177.         speedArray[s] = distance;
  178.         s++;
  179.         if (b == 4)
  180.         {
  181.             Vector3 temp1 = PositionArray1[1];
  182.             Vector3 temp2 = PositionArray1[2];

  183.             //修改中间两点坐标
  184.             Vector3 middle = (PositionArray1[0] + PositionArray1[2]) / 2;
  185.             PositionArray1[1] = (PositionArray1[1] - middle) * 1.5f + middle;
  186.             middle = (temp1 + PositionArray1[3]) / 2;
  187.             PositionArray1[2] = (PositionArray1[2] - middle) * 2.1f + middle;

  188.             for (int index1 = 0; index1 < num / 1.5f; index1++)
  189.             {
  190.                 float t1 = (1.0f / num) * index1;
  191.                 Vector3 target = Mathf.Pow(1 - t1, 3) * PositionArray1[0] +
  192.                                  3 * PositionArray1[1] * t1 * Mathf.Pow(1 - t1, 2) +
  193.                                  3 * PositionArray1[2] * t1 * t1 * (1 - t1) + PositionArray1[3] * Mathf.Pow(t1, 3);
  194.                 //float deltaspeed = (float)(distance - lastDistance) / num;
  195.                 //获取速度差值(存在问题,参考)
  196.                 float deltaspeed = (float)(speedArray[3] - speedArray[0]) / num;
  197.                 //float randomOffset = Random.Range(-1/(speedArray[0] + (deltaspeed * index1)), 1 / (speedArray[0] + (deltaspeed * index1)));
  198.                 //模拟毛刺效果
  199.                 float randomOffset = Random.Range(-targetPosOffset, targetPosOffset);
  200.                 DrawBrush(texRender, (int)(target.x + randomOffset), (int)(target.y + randomOffset), brushTypeTexture, brushColor, SetScale(speedArray[0] + (deltaspeed * index1)));
  201.             }

  202.             PositionArray1[0] = temp1;
  203.             PositionArray1[1] = temp2;
  204.             PositionArray1[2] = PositionArray1[3];

  205.             speedArray[0] = speedArray[1];
  206.             speedArray[1] = speedArray[2];
  207.             speedArray[2] = speedArray[3];
  208.             b = 3;
  209.             s = 3;
  210.         }
  211.         else
  212.         {
  213.             DrawBrush(texRender, (int)endPosition.x, (int)endPosition.y, brushTypeTexture,
  214.                 brushColor, brushScale);
  215.         }

  216.     }
  217. }
  218. [code]Shadercode:
  219. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

  220. Shader "Painting"
  221. {
  222.         Properties
  223.         {
  224.                 _MainTex("MainTex (RGB) Trans (A)", 2D) = "white" {}
  225.                 _Color("Color", Color) = (1,1,1,0)
  226.         }

  227.                 SubShader
  228.                 {
  229.                         Tags
  230.                         {
  231.                                 "Queue" = "Transparent"
  232.                                 "IgnoreProjector" = "True"
  233.                                 "RenderType" = "Transparent"
  234.                                 "PreviewType" = "Plane"
  235.                                 "CanUseSpriteAtlas" = "True"
  236.                         }

  237.                         Cull Off
  238.                         Lighting Off
  239.                         ZWrite Off
  240.                         Fog { Mode Off }
  241.                         Blend One OneMinusSrcAlpha

  242.                         Pass
  243.                         {
  244.                                 CGPROGRAM
  245.                                 #pragma vertex vert
  246.                                 #pragma fragment frag
  247.                                 #include "UnityCG.cginc"

  248.                                 struct v2f
  249.                                 {
  250.                                         float4 vertex : SV_POSITION;
  251.                                         half2 texcoord : TEXCOORD0;
  252.                                 };

  253.                                 fixed4 _Color;

  254.                                 v2f vert(appdata_base IN)
  255.                                 {
  256.                                         v2f OUT;
  257.                                         OUT.vertex = UnityObjectToClipPos(IN.vertex);
  258.                                         OUT.texcoord = IN.texcoord;
  259.                                         return OUT;
  260.                                 }

  261.                                 sampler2D _MainTex;

  262.                                 fixed4 frag(v2f IN) : SV_Target
  263.                                 {
  264.                                         float4 col = _Color * tex2D(_MainTex, IN.texcoord);
  265.                                         col.rgb *= col.a;
  266.                                         return col;
  267.                                 }
  268.                                 ENDCG
  269.                         }
  270.                 }
  271. }
复制代码
分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

关闭

站长推荐上一条 /1 下一条

手机版|纳金网 ( 闽ICP备08008928号

GMT+8, 2024-5-4 10:33 , Processed in 0.087843 second(s), 29 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部