MPImageBasic.shader 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. Shader "MPUI/Basic Procedural Image"
  2. {
  3. Properties
  4. {
  5. [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" { }
  6. _Color ("Tint", Color) = (1,1,1,1)
  7. _StencilComp ("Stencil Comparison", Float) = 8
  8. _Stencil ("Stencil ID", Float) = 0
  9. _StencilOp ("Stencil Operation", Float) = 0
  10. _StencilWriteMask ("Stencil Write Mask", Float) = 255
  11. _StencilReadMask ("Stencil Read Mask", Float) = 255
  12. _ColorMask ("Color Mask", Float) = 15
  13. /* //SOFTMASK_HANDLE_START
  14. [PerRendererData] _SoftMask ("Mask", 2D) = "white" {}
  15. */ //SOFTMASK_HANDLE_END
  16. [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
  17. }
  18. SubShader
  19. {
  20. Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" "PreviewType" = "Plane" "CanUseSpriteAtlas" = "True" }
  21. Stencil
  22. {
  23. Ref [_Stencil]
  24. Comp [_StencilComp]
  25. Pass [_StencilOp]
  26. ReadMask [_StencilReadMask]
  27. WriteMask [_StencilWriteMask]
  28. }
  29. Cull Off
  30. Lighting Off
  31. ZWrite Off
  32. ZTest [unity_GUIZTestMode]
  33. Blend SrcAlpha OneMinusSrcAlpha
  34. ColorMask [_ColorMask]
  35. Pass
  36. {
  37. Name "Default"
  38. CGPROGRAM
  39. #pragma vertex vert
  40. #pragma fragment frag
  41. #include "UnityCG.cginc"
  42. #include "UnityUI.cginc"
  43. #include "2D_SDF.cginc"
  44. /* //SOFTMASK_HANDLE_START
  45. #include "Assets/SoftMask/Shaders/SoftMask.cginc" //SOFTMASK_INCLUDE_HANDLE
  46. */ //SOFTMASK_HANDLE_END
  47. #pragma multi_compile_local _ UNITY_UI_CLIP_RECT
  48. #pragma multi_compile_local _ UNITY_UI_ALPHACLIP
  49. #pragma multi_compile_local _ CIRCLE TRIANGLE RECTANGLE NSTAR_POLYGON
  50. #pragma multi_compile_local _ STROKE OUTLINED OUTLINED_STROKE
  51. /* //SOFTMASK_HANDLE_START
  52. #pragma multi_compile _ SOFTMASK_SIMPLE
  53. */ //SOFTMASK_HANDLE_END
  54. struct appdata_t
  55. {
  56. float4 vertex: POSITION;
  57. float4 color: COLOR;
  58. float2 uv0: TEXCOORD0;
  59. float2 uv1: TEXCOORD1;
  60. float2 uv2: TEXCOORD2;
  61. float2 uv3: TEXCOORD3;
  62. float3 normal: NORMAL;
  63. float4 tangent: TANGENT;
  64. UNITY_VERTEX_INPUT_INSTANCE_ID
  65. };
  66. struct v2f
  67. {
  68. float4 vertex: SV_POSITION;
  69. fixed4 color: COLOR;
  70. float2 uv0: TEXCOORD0;
  71. float4 sizeData: TEXCOORD1;
  72. float4 strokeOutlineCornerData: TEXCOORD2;
  73. fixed4 outlineColor: COLOR1;
  74. float4 shapeData: TEXCOORD3;
  75. float4 worldPosition: TEXCOORD4;
  76. /* //SOFTMASK_HANDLE_START
  77. SOFTMASK_COORDS(5)
  78. */ //SOFTMASK_HANDLE_END
  79. UNITY_VERTEX_OUTPUT_STEREO
  80. };
  81. sampler2D _MainTex;
  82. fixed4 _Color;
  83. fixed4 _TextureSampleAdd;
  84. float4 _ClipRect;
  85. float4 _MainTex_ST;
  86. #if RECTANGLE
  87. half rectangleScene(float4 _sizeData, float4 _shapeData, float _cornerStyle)
  88. {
  89. float2 _texcoord = _sizeData.xy;
  90. float2 _size = float2(_sizeData.z, _sizeData.w);
  91. float4 radius = _shapeData;
  92. half4 c = half4(_texcoord, _size - _texcoord);
  93. half rect = min(min(min(c.x, c.y), c.z), c.w);
  94. bool4 cornerRects;
  95. cornerRects.x = _texcoord.x < radius.x && _texcoord.y < radius.x;
  96. cornerRects.y = _texcoord.x > _size.x - radius.y && _texcoord.y < radius.y;
  97. cornerRects.z = _texcoord.x > _size.x - radius.z && _texcoord.y > _size.y - radius.z;
  98. cornerRects.w = _texcoord.x < radius.w && _texcoord.y > _size.y - radius.w;
  99. half cornerMask = any(cornerRects);
  100. half4 cornerCircles;
  101. cornerCircles.x = radius.x - length(_texcoord - radius.xx);//circle(_texcoord - radius.xx, radius.x);
  102. cornerCircles.y = radius.y - length(_texcoord - half2(_size.x - radius.y, radius.y));//circle(_texcoord - half2(_size.x - radius.y, radius.y), radius.y);
  103. cornerCircles.z = radius.z - length(_texcoord - (half2(_size.x, _size.y) - radius.zz));//circle(_texcoord - (half2(_size.x, _size.y) - radius.zz), radius.z);
  104. cornerCircles.w = radius.w - length(_texcoord - half2(radius.w, _size.y - radius.w)); //circle(_texcoord - half2(radius.w, _size.y - radius.w), radius.w);
  105. cornerCircles = min(max(cornerCircles, 0) * cornerRects, rect);
  106. //cornerCircles = max(cornerCircles, 0) * cornerRects;
  107. half corners = max(max(max(cornerCircles.x, cornerCircles.y), cornerCircles.z), cornerCircles.w);
  108. corners = max(corners, 0.0) * cornerMask;
  109. //return rect;
  110. return rect*(cornerMask-1) - corners;
  111. /*
  112. half rect = rectanlge(_texcoord - half2(_size.x / 2.0, _size.y / 2.0), _size.x, _size.y);
  113. half cornerCircle = circle(_texcoord - radius.xx, radius.x);
  114. rect = _texcoord.x < radius.x && _texcoord.y < radius.x ? cornerCircle: rect;
  115. cornerCircle = circle(_texcoord - half2(_size.x - radius.y, radius.y), radius.y);
  116. rect = _texcoord.x > _size.x - radius.y && _texcoord.y < radius.y ? cornerCircle: rect;
  117. cornerCircle = circle(_texcoord - (half2(_size.x, _size.y) - radius.zz), radius.z);
  118. rect = _texcoord.x > _size.x - radius.z && _texcoord.y > _size.y - radius.z ? cornerCircle: rect;
  119. cornerCircle = circle(_texcoord - half2(radius.w, _size.y - radius.w), radius.w);
  120. rect = _texcoord.x < radius.w && _texcoord.y > _size.y - radius.w ? cornerCircle: rect;
  121. */
  122. //max(max(max(cornerCircles.x, cornerCircles.y), cornerCircles.z), cornerCircles.w);
  123. }
  124. #endif
  125. #if CIRCLE
  126. float circleScene(float4 _sizeData, float4 _shapeData)
  127. {
  128. float2 _texcoord = _sizeData.xy;
  129. float2 _size = _sizeData.zw;
  130. float width = _size.x;
  131. float height = _size.y;
  132. float radius = lerp(_shapeData.x, min(width, height) / 2.0, _shapeData.y);
  133. float sdf = circle(_texcoord - float2(width / 2.0, height / 2.0), radius);
  134. return sdf;
  135. }
  136. #endif
  137. #if TRIANGLE
  138. half triangleScene(float4 _sizeData, float4 _shapeData)
  139. {
  140. float2 _texcoord = _sizeData.xy;
  141. float2 _size = _sizeData.zw;
  142. float width = _size.x;//_additionalData.z;
  143. float height = _size.y;//_additionalData.w;
  144. half sdf = sdTriangleIsosceles(_texcoord - half2(width / 2.0, height), half2(width / 2.0, -height));
  145. //return sdf;
  146. float3 _TriangleCornerRadius = max(_shapeData.xyz, float3(0.001, 0.001, 0.001));
  147. // Left Corner
  148. half halfWidth = width / 2.0;
  149. half m = height / halfWidth;
  150. half d = sqrt(1.0 + m * m);
  151. half c = 0.0;
  152. half k = -_TriangleCornerRadius.x * d + c;
  153. half x = (_TriangleCornerRadius.x - k) / m;
  154. half2 circlePivot = half2(x, _TriangleCornerRadius.x);
  155. half cornerCircle = circle(_texcoord - circlePivot, _TriangleCornerRadius.x);
  156. //sdf = sdfDifference(sdf, cornerCircle);
  157. //return sdf;
  158. x = (circlePivot.y + circlePivot.x / m - c) / (m + 1.0 / m);
  159. half y = m * x + c;
  160. half fy = map(_texcoord.x, x, circlePivot.x, y, circlePivot.y);
  161. sdf = _texcoord.y < fy && _texcoord.x < circlePivot.x ? cornerCircle: sdf;
  162. //return sdf;
  163. // Right Corner
  164. m = -m; c = 2.0 * height;
  165. k = -_TriangleCornerRadius.y * d + c;
  166. x = (_TriangleCornerRadius.y - k) / m;
  167. circlePivot = half2(x, _TriangleCornerRadius.y);
  168. cornerCircle = circle(_texcoord - circlePivot, _TriangleCornerRadius.y);
  169. x = (circlePivot.y + circlePivot.x / m - c) / (m + 1.0 / m); y = m * x + c;
  170. fy = map(_texcoord.x, circlePivot.x, x, circlePivot.y, y);
  171. sdf = _texcoord.x > circlePivot.x && _texcoord.y < fy ? cornerCircle: sdf;
  172. //Top Corner
  173. k = -_TriangleCornerRadius.z * sqrt(1.0 + m * m) + c;
  174. y = m * (width / 2.0) + k;
  175. circlePivot = half2(halfWidth, y);
  176. cornerCircle = circle(_texcoord - circlePivot, _TriangleCornerRadius.z);
  177. x = (circlePivot.y + circlePivot.x / m - c) / (m + 1.0 / m); y = m * x + c;
  178. fy = map(_texcoord.x, width - x, x, -1.0, 1.0);
  179. fy = lerp(circlePivot.y, y, abs(fy));
  180. sdf = _texcoord.y > fy ? cornerCircle: sdf;
  181. return sdf;
  182. }
  183. #endif
  184. #if NSTAR_POLYGON
  185. half nStarPolygonScene(float4 _sizeData, float4 _shapeData)
  186. {
  187. float2 _texcoord = _sizeData.xy;
  188. float width = _sizeData.z;
  189. float height = _sizeData.w;
  190. float size = height / 2 - _shapeData.y;
  191. half str = sdNStarPolygon(_texcoord - half2(width / 2, height / 2), size, _shapeData.x, _shapeData.z) - _shapeData.y;
  192. return str;
  193. }
  194. #endif
  195. float2 rotateUV(float2 uv, float rotation, float2 mid)
  196. {
  197. return float2(
  198. cos(rotation) * (uv.x - mid.x) + sin(rotation) * (uv.y - mid.y) + mid.x,
  199. cos(rotation) * (uv.y - mid.y) - sin(rotation) * (uv.x - mid.x) + mid.y
  200. );
  201. }
  202. float4 decode_0_1_16(float2 input){
  203. float m = 65535.0;
  204. float e = 256.0 / 255.0;
  205. float n = 1.0 / m;
  206. float4 c = float4(input.x, input.x, input.y, input.y);
  207. c.yw *= m;
  208. c = frac(c);
  209. c -= float4(c.y, 0.0, c.w, 0.0) * n;
  210. return clamp(c * e, 0.0, 1.0);
  211. }
  212. v2f vert(appdata_t v)
  213. {
  214. v2f OUT;
  215. UNITY_SETUP_INSTANCE_ID(v);
  216. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
  217. OUT.vertex = UnityObjectToClipPos(v.vertex);
  218. OUT.worldPosition = v.vertex;
  219. OUT.color = v.color * _Color;
  220. OUT.uv0 = v.uv0;
  221. float2 size = v.uv1;
  222. half strokeWidth = v.normal.y;
  223. half falloff = v.normal.z;
  224. float rotationData = v.uv3.x;
  225. half cornerStyle = v.uv3.y;
  226. half outlineWidth = v.normal.x;
  227. half4 outlineColor = v.tangent;
  228. float4 shapeData;
  229. #if CIRCLE
  230. shapeData.xy = v.uv2.xy;
  231. #else
  232. shapeData = decode_0_1_16(v.uv2) * min(size.x, size.y);
  233. #endif
  234. OUT.strokeOutlineCornerData = float4(strokeWidth, falloff, outlineWidth, cornerStyle);
  235. OUT.outlineColor = outlineColor;
  236. OUT.shapeData = shapeData;
  237. // Rotation Values
  238. half sign = rotationData > 0.0 ? 1 : -1;
  239. float f = abs(rotationData);
  240. float shapeRotation = frac(f) * 360.0 * sign;
  241. // r.xyz -> constrainRotation, flipHorizontal, flipVertical
  242. f = floor(f);
  243. float p = f / 100.0;
  244. float z = round(p);
  245. p = frac(p) * 10.0;
  246. float y = round(p);
  247. p = frac(p) * 10.0;
  248. float x = round(p);
  249. half constrainRotation = x;
  250. half flipHorizontal = y;
  251. half flipVertical = z;
  252. shapeRotation = radians(shapeRotation);
  253. size = constrainRotation > 0.0 && frac(abs(shapeRotation) / 3.14159) > 0.1? float2(size.y, size.x) : size;
  254. float2 shapeUv = constrainRotation > 0 ? v.uv0 : v.uv0 * size;
  255. shapeUv = rotateUV(shapeUv, shapeRotation, constrainRotation > 0? float2(0.5, 0.5) : size * 0.5);
  256. shapeUv*= constrainRotation > 0.0? size : 1.0;
  257. shapeUv.x = lerp(shapeUv.x, abs(size.x - shapeUv.x), flipHorizontal);
  258. shapeUv.y = lerp(shapeUv.y, abs(size.y - shapeUv.y), flipVertical);
  259. OUT.sizeData = float4(shapeUv.x, shapeUv.y, size.x, size.y);
  260. #ifdef UNITY_HALF_TEXEL_OFFSET
  261. OUT.vertex.xy += (_ScreenParams.zw - 1.0) * float2(-1.0, 1.0);
  262. #endif
  263. /* //SOFTMASK_HANDLE_START
  264. SOFTMASK_CALCULATE_COORDS(OUT, v.vertex);
  265. */ //SOFTMASK_HANDLE_END
  266. return OUT;
  267. }
  268. fixed4 frag(v2f IN): SV_Target
  269. {
  270. half4 color = IN.color;
  271. half2 texcoord = IN.uv0;
  272. color = (tex2D(_MainTex, texcoord) + _TextureSampleAdd) * color;
  273. float4 sizeData = IN.sizeData;
  274. float strokeWidth = IN.strokeOutlineCornerData.x;
  275. float falloff = IN.strokeOutlineCornerData.y;
  276. float outlineWidth = IN.strokeOutlineCornerData.z;
  277. half4 outlineColor = IN.outlineColor;
  278. float cornerStyle = IN.strokeOutlineCornerData.w;
  279. float4 shapeData = IN.shapeData;
  280. half pixelScale = clamp(1.0/falloff, 1.0/2048.0, 2048.0);
  281. float sdfData = 0;
  282. #if RECTANGLE
  283. sdfData = rectangleScene(sizeData, shapeData, cornerStyle);
  284. #endif
  285. #if CIRCLE
  286. sdfData = circleScene(sizeData, shapeData);
  287. #endif
  288. #if TRIANGLE
  289. sdfData = triangleScene(sizeData, shapeData);
  290. #endif
  291. #if NSTAR_POLYGON
  292. sdfData = nStarPolygonScene(sizeData, shapeData);
  293. #endif
  294. #if !OUTLINED && !STROKE && !OUTLINED_STROKE
  295. half shape = sampleSdf(sdfData, pixelScale);
  296. color.a *= shape;
  297. //color.a = sdfData;
  298. #endif
  299. #if STROKE
  300. half shape = sampleSdfStrip(sdfData, strokeWidth, pixelScale);
  301. color.a *= shape;
  302. #endif
  303. #if OUTLINED
  304. float alpha = sampleSdf(sdfData, pixelScale);
  305. float lerpFac = sampleSdf(sdfData + outlineWidth, pixelScale);
  306. color = half4(lerp(outlineColor.rgb, color.rgb, lerpFac), lerp(outlineColor.a * color.a, color.a, lerpFac));
  307. color.a *= alpha;
  308. #endif
  309. #if OUTLINED_STROKE
  310. float alpha = sampleSdfStrip(sdfData, outlineWidth + strokeWidth, pixelScale);
  311. float lerpFac = sampleSdfStrip(sdfData + outlineWidth, strokeWidth + falloff, pixelScale);
  312. lerpFac = clamp(lerpFac, 0, 1);
  313. color = half4(lerp(outlineColor.rgb, color.rgb, lerpFac), lerp(outlineColor.a * color.a, color.a, lerpFac));
  314. color.a *= alpha;
  315. #endif
  316. /* //SOFTMASK_HANDLE_START
  317. color.a *= SOFTMASK_GET_MASK(IN);
  318. */ //SOFTMASK_HANDLE_END
  319. #ifdef UNITY_UI_CLIP_RECT
  320. color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
  321. #endif
  322. #ifdef UNITY_UI_ALPHACLIP
  323. clip(color.a - 0.001);
  324. #endif
  325. return fixed4(color);
  326. }
  327. ENDCG
  328. }
  329. }
  330. CustomEditor "MPUIKIT.Editor.MPImageShaderGUI"
  331. }