失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > unity 毛笔字笔触(画图)

unity 毛笔字笔触(画图)

时间:2020-10-13 10:54:23

相关推荐

unity 毛笔字笔触(画图)

毛笔字笔触

RawImage

using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;using Random = UnityEngine.Random;public class Painting : MonoBehaviour{private RenderTexture texRender; //画布public Material mat;//给定的shader新建材质public Texture brushTypeTexture; //画笔纹理,半透明private Camera mainCamera;private float brushScale = 0.5f;public Color brushColor = Color.black;public RawImage raw; //使用UGUI的RawImage显示,方便进行添加UI,将pivot设为(0.5,0.5)public RawImage raw2; //使用UGUI的RawImage显示,方便进行添加UI,将pivot设为(0.5,0.5)public RawImage raw3; //使用UGUI的RawImage显示,方便进行添加UI,将pivot设为(0.5,0.5)private float lastDistance;private Vector3[] PositionArray = new Vector3[3];private int a = 0;private Vector3[] PositionArray1 = new Vector3[4];private int b = 0;private float[] speedArray = new float[4];private int s = 0;[SerializeField]private int num = 50; //画的两点之间插件点的个数public float widthPower = 0.5f; //关联粗细Vector2 rawMousePosition; //raw图片的左下角对应鼠标位置float rawWidth; //raw图片宽度float rawHeight;//raw图片长度[SerializeField]private const int maxCancleStep = 5; //最大撤销的步骤(越大越耗费内存)[SerializeField]private Stack<RenderTexture> savedList = new Stack<RenderTexture>(maxCancleStep);void Start(){//raw图片鼠标位置,宽度计算rawWidth = raw.rectTransform.sizeDelta.x;rawHeight = raw.rectTransform.sizeDelta.y;Vector2 rawanchorPositon = new Vector2(raw.rectTransform.anchoredPosition.x - raw.rectTransform.sizeDelta.x / 2.0f, raw.rectTransform.anchoredPosition.y - raw.rectTransform.sizeDelta.y / 2.0f);//计算Canvas位置偏差Canvas canvas=raw.canvas;Vector2 canvasOffset=RectTransformUtility.WorldToScreenPoint(Camera.main,canvas.transform.position) - canvas.GetComponent<RectTransform>().sizeDelta/2;//最终鼠标相对画布的位置rawMousePosition = rawanchorPositon + new Vector2(Screen.width / 2.0f, Screen.height / 2.0f) + canvasOffset;texRender = new RenderTexture(Screen.width, Screen.height, 24, RenderTextureFormat.ARGB1555);Clear(texRender);}Vector3 startPosition = Vector3.zero;Vector3 endPosition = Vector3.zero;void Update(){if (Input.GetMouseButtonDown(0)){SaveTexture();}if (Input.GetMouseButton(0)){OnMouseMove(new Vector3(Input.mousePosition.x+ 123.06f, Input.mousePosition.y + 45.25f, 0));}if (Input.GetMouseButtonUp(0)){OnMouseUp();}if (Input.GetKeyDown(KeyCode.R)){CanclePaint();}if (Input.GetKeyDown(KeyCode.C)){OnClickClear();}DrawImage();}[SerializeField] private RawImage saveImage;void SaveTexture(){RenderTexture newRenderTexture = new RenderTexture(texRender);Graphics.Blit(texRender,newRenderTexture);savedList.Push(newRenderTexture);}void CanclePaint(){if (savedList.Count > 0){texRender.Release();texRender = savedList.Pop();}}void OnMouseUp(){startPosition = Vector3.zero;//brushScale = 0.5f;a = 0;b = 0;s = 0;}//设置画笔宽度float SetScale(float distance){float Scale = 0;if (distance < 100){Scale = 0.8f - 0.005f * distance;}else{Scale = 0.425f - 0.00125f * distance;}if (Scale <= 0.05f){Scale = 0.05f;}return Scale * widthPower;}void OnMouseMove(Vector3 pos){if (startPosition == Vector3.zero){startPosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0);}endPosition = pos;float distance = Vector3.Distance(startPosition, endPosition);brushScale = SetScale(distance);ThreeOrderBézierCurse(pos, distance, 4.5f);startPosition = endPosition;lastDistance = distance;}void Clear(RenderTexture destTexture){Graphics.SetRenderTarget(destTexture);GL.PushMatrix();Color color = new Color(0,0,0,0);GL.Clear(true, true, color);GL.PopMatrix();}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);}void DrawBrush(RenderTexture destTexture, Rect destRect, Texture sourceTexture, Color color, float scale){//增加鼠标位置根据raw图片位置换算。float left = (destRect.xMin-rawMousePosition.x)*Screen.width/rawWidth - destRect.width * scale / 2.0f;float right = (destRect.xMin - rawMousePosition.x) * Screen.width / rawWidth + destRect.width * scale / 2.0f;float top = (destRect.yMin - rawMousePosition.y) *Screen.height / rawHeight - destRect.height * scale / 2.0f;float bottom = (destRect.yMin - rawMousePosition.y) * Screen.height / rawHeight + destRect.height * scale / 2.0f;Graphics.SetRenderTarget(destTexture);GL.PushMatrix();GL.LoadOrtho();mat.SetTexture("_MainTex", brushTypeTexture);mat.SetColor("_Color", color);mat.SetPass(0);GL.Begin(GL.QUADS);GL.TexCoord2(0.0f, 0.0f); GL.Vertex3(left / Screen.width, top / Screen.height, 0);GL.TexCoord2(1.0f, 0.0f); GL.Vertex3(right / Screen.width, top / Screen.height, 0);GL.TexCoord2(1.0f, 1.0f); GL.Vertex3(right / Screen.width, bottom / Screen.height, 0);GL.TexCoord2(0.0f, 1.0f); GL.Vertex3(left / Screen.width, bottom / Screen.height, 0);GL.End();GL.PopMatrix();}bool bshow = true;void DrawImage(){raw.texture = texRender;raw2.texture = texRender;raw3.texture = texRender;}public void OnClickClear(){Clear(texRender);savedList.Clear();}//二阶贝塞尔曲线 效果不好,改用下面三阶public void TwoOrderBézierCurse(Vector3 pos, float distance){PositionArray[a] = pos;a++;if (a == 3){for (int index = 0; index < num; index++){Vector3 middle = (PositionArray[0] + PositionArray[2]) / 2;PositionArray[1] = (PositionArray[1] - middle) / 2 + middle;float t = (1.0f / num) * index / 2;Vector3 target = Mathf.Pow(1 - t, 2) * PositionArray[0] + 2 * (1 - t) * t * PositionArray[1] +Mathf.Pow(t, 2) * PositionArray[2];float deltaSpeed = (float)(distance - lastDistance) / num;DrawBrush(texRender, (int)target.x, (int)target.y, brushTypeTexture, brushColor, SetScale(lastDistance + (deltaSpeed * index)));}PositionArray[0] = PositionArray[1];PositionArray[1] = PositionArray[2];a = 2;}else{DrawBrush(texRender, (int)endPosition.x, (int)endPosition.y, brushTypeTexture,brushColor, brushScale);}}//三阶贝塞尔曲线,获取连续4个点坐标,通过调整中间2点坐标,画出部分(我使用了num/1.5实现画出部分曲线)来使曲线平滑;通过速度控制曲线宽度。private void ThreeOrderBézierCurse(Vector3 pos, float distance, float targetPosOffset){//记录坐标PositionArray1[b] = pos;b++;//记录速度speedArray[s] = distance;s++;if (b == 4){Vector3 temp1 = PositionArray1[1];Vector3 temp2 = PositionArray1[2];//修改中间两点坐标Vector3 middle = (PositionArray1[0] + PositionArray1[2]) / 2;PositionArray1[1] = (PositionArray1[1] - middle) * 1.5f + middle;middle = (temp1 + PositionArray1[3]) / 2;PositionArray1[2] = (PositionArray1[2] - middle) * 2.1f + middle;for (int index1 = 0; index1 < num / 1.5f; index1++){float t1 = (1.0f / num) * index1;Vector3 target = Mathf.Pow(1 - t1, 3) * PositionArray1[0] +3 * PositionArray1[1] * t1 * Mathf.Pow(1 - t1, 2) +3 * PositionArray1[2] * t1 * t1 * (1 - t1) + PositionArray1[3] * Mathf.Pow(t1, 3);//float deltaspeed = (float)(distance - lastDistance) / num;//获取速度差值(存在问题,参考)float deltaspeed = (float)(speedArray[3] - speedArray[0]) / num;//float randomOffset = Random.Range(-1/(speedArray[0] + (deltaspeed * index1)), 1 / (speedArray[0] + (deltaspeed * index1)));//模拟毛刺效果float randomOffset = Random.Range(-targetPosOffset, targetPosOffset);DrawBrush(texRender, (int)(target.x + randomOffset), (int)(target.y + randomOffset), brushTypeTexture, brushColor, SetScale(speedArray[0] + (deltaspeed * index1)));}PositionArray1[0] = temp1;PositionArray1[1] = temp2;PositionArray1[2] = PositionArray1[3];speedArray[0] = speedArray[1];speedArray[1] = speedArray[2];speedArray[2] = speedArray[3];b = 3;s = 3;}else{DrawBrush(texRender, (int)endPosition.x, (int)endPosition.y, brushTypeTexture,brushColor, brushScale);}}}

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader "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 = UnityObjectToClipPos(IN.vertex);OUT.texcoord = IN.texcoord;return OUT;}sampler2D _MainTex;fixed4 frag(v2f IN) : SV_Target{float4 texColor = tex2D(_MainTex, IN.texcoord);float value = step(_Color.r + _Color.g + _Color.b, 0.1f);float4 col = (1 - texColor) * (1 - value) * _Color + texColor * value;col.a = texColor.a; col.rgb *= col.a;return col;}ENDCG}}}

关键点

场景package:/download/weixin_45023328/81875160

如果觉得《unity 毛笔字笔触(画图)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。