SDK_OutLine.shader 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. Shader "ShadowSDK/HandEvent_OutLine"
  2. {
  3. Properties
  4. {
  5. [PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}
  6. _Color("Main texture Tint", Color) = (1,1,1,1)
  7. [Header(General Settings)]
  8. [MaterialToggle] _OutlineEnabled("Outline Enabled", Float) = 1
  9. [MaterialToggle] _ConnectedAlpha("Connected Alpha", Float) = 0
  10. [HideInInspector] _AlphaThreshold("Alpha clean", Range(0, 1)) = 0
  11. _Thickness("Width (Max recommended 100)", float) = 10
  12. [KeywordEnum(Solid, Gradient, Image)] _OutlineMode("Outline mode", Float) = 0
  13. [KeywordEnum(Contour, Frame)] _OutlineShape("Outline shape", Float) = 0
  14. [KeywordEnum(Inside under sprite, Inside over sprite, Outside)] _OutlinePosition("Outline Position (Frame Only)", Float) = 0
  15. [Header(Solid Settings)]
  16. _SolidOutline("Outline Color Base", Color) = (1,1,1,1)
  17. [Header(Gradient Settings)]
  18. _GradientOutline1("Outline Color 1", Color) = (1,1,1,1)
  19. _GradientOutline2("Outline Color 2", Color) = (1,1,1,1)
  20. _Weight("Weight", Range(0, 1)) = 0.5
  21. _Angle("Gradient Angle (General gradient Only)", float) = 45
  22. //[KeywordEnum(General, Frame directed)] _FrameMode("Frame Mode (Frame Only)", Float) = 0
  23. [Header(Image Settings)]
  24. _FrameTex("Frame Texture", 2D) = "white" {}
  25. _ImageOutline("Outline Color Base", Color) = (1,1,1,1)
  26. [KeywordEnum(Stretch, Tile)] _TileMode("Frame mode", Float) = 0
  27. }
  28. SubShader
  29. {
  30. Tags
  31. {
  32. "Queue" = "Transparent"
  33. "IgnoreProjector" = "True"
  34. "RenderType" = "Transparent"
  35. "PreviewType" = "Plane"
  36. "CanUseSpriteAtlas" = "True"
  37. }
  38. Cull Off
  39. Lighting Off
  40. ZWrite Off
  41. Blend One OneMinusSrcAlpha
  42. Pass
  43. {
  44. CGPROGRAM
  45. #pragma vertex vert
  46. #pragma fragment frag
  47. #pragma multi_compile _ PIXELSNAP_ON
  48. #pragma exclude_renderers d3d11_9x
  49. #include "UnityCG.cginc"
  50. struct appdata_t
  51. {
  52. float4 vertex : POSITION;
  53. float4 color : COLOR;
  54. float2 texcoord : TEXCOORD0;
  55. };
  56. struct v2f
  57. {
  58. float4 vertex : SV_POSITION;
  59. fixed4 color : COLOR;
  60. float2 texcoord : TEXCOORD0;
  61. };
  62. fixed4 _Color;
  63. fixed _Thickness;
  64. fixed _OutlineEnabled;
  65. fixed _ConnectedAlpha;
  66. fixed _OutlineShape;
  67. fixed _OutlinePosition;
  68. fixed _OutlineMode;
  69. fixed4 _SolidOutline;
  70. fixed4 _GradientOutline1;
  71. fixed4 _GradientOutline2;
  72. fixed _Weight;
  73. fixed _AlphaThreshold;
  74. fixed _Angle;
  75. //fixed _FrameMode;
  76. fixed4 _ImageOutline;
  77. fixed _TileMode;
  78. v2f vert(appdata_t IN)
  79. {
  80. v2f OUT;
  81. OUT.vertex = UnityObjectToClipPos(IN.vertex);
  82. OUT.texcoord = IN.texcoord;
  83. OUT.color = IN.color * _Color;
  84. #ifdef PIXELSNAP_ON
  85. OUT.vertex = UnityPixelSnap(OUT.vertex);
  86. #endif
  87. return OUT;
  88. }
  89. sampler2D _MainTex;
  90. sampler2D _AlphaTex;
  91. float _AlphaSplitEnabled;
  92. uniform float4 _MainTex_TexelSize;
  93. sampler2D _FrameTex;
  94. uniform float4 _FrameTex_TexelSize;
  95. uniform float4 _FrameTex_ST;
  96. fixed4 SampleSpriteTexture(float2 uv)
  97. {
  98. float2 offsets;
  99. if ((_OutlinePosition != 2 && _OutlineShape == 1) || _OutlineEnabled == 0) // not outside and frame
  100. {
  101. offsets = float2(0, 0);
  102. }
  103. else
  104. {
  105. offsets = float2(_Thickness * 2, _Thickness * 2);
  106. }
  107. float2 bigsize = float2(_MainTex_TexelSize.z, _MainTex_TexelSize.w);
  108. float2 smallsize = float2(_MainTex_TexelSize.z - offsets.x, _MainTex_TexelSize.w - offsets.y);
  109. float2 uv_changed = float2
  110. (
  111. uv.x * bigsize.x / smallsize.x - 0.5 * offsets.x / smallsize.x,
  112. uv.y * bigsize.y / smallsize.y - 0.5 * offsets.y / smallsize.y
  113. );
  114. if (uv_changed.x < 0 || uv_changed.x > 1 || uv_changed.y < 0 || uv_changed.y > 1)
  115. {
  116. return float4(0, 0, 0, 0);
  117. }
  118. fixed4 color = tex2D(_MainTex, uv_changed);
  119. #if UNITY_TEXTURE_ALPHASPLIT_ALLOWED
  120. if (_AlphaSplitEnabled)
  121. color.a = tex2D(_AlphaTex, uv).r;
  122. #endif //UNITY_TEXTURE_ALPHASPLIT_ALLOWED
  123. return color;
  124. }
  125. bool CheckOriginalSpriteTexture(float2 uv, bool ifZero)
  126. {
  127. float thicknessX = _Thickness / _MainTex_TexelSize.z;
  128. float thicknessY = _Thickness / _MainTex_TexelSize.w;
  129. int steps = 100;
  130. float angle_step = 360.0 / steps;
  131. float alphaThreshold = _AlphaThreshold / 10;
  132. float alphaCount = _AlphaThreshold * 10;
  133. // check if the basic points has an alpha to speed up the process and not use the for loop
  134. bool outline = false;
  135. float alphaCounter = 0;
  136. if (ifZero)
  137. {
  138. }
  139. else
  140. {
  141. outline = SampleSpriteTexture(uv + fixed2(0, +thicknessY)).a > alphaThreshold ||
  142. SampleSpriteTexture(uv + fixed2(0, -thicknessY)).a > alphaThreshold ||
  143. SampleSpriteTexture(uv + fixed2(+thicknessX, 0)).a > alphaThreshold ||
  144. SampleSpriteTexture(uv + fixed2(-thicknessX, 0)).a > alphaThreshold ||
  145. SampleSpriteTexture(uv + fixed2(+thicknessX * cos(3.14 / 4), -thicknessY * sin(3.14 / 4))).a > alphaThreshold ||
  146. SampleSpriteTexture(uv + fixed2(-thicknessX * cos(3.14 / 4), +thicknessY * sin(3.14 / 4))).a > alphaThreshold ||
  147. SampleSpriteTexture(uv + fixed2(-thicknessX * cos(3.14 / 4), -thicknessY * sin(3.14 / 4))).a > alphaThreshold ||
  148. SampleSpriteTexture(uv + fixed2(+thicknessX * cos(3.14 / 4), +thicknessY * sin(3.14 / 4))).a > alphaThreshold;
  149. }
  150. if (outline) return outline;
  151. for (int i = 0; i < steps; i++) // high number and not a variable to avoid stupid compiler bugs
  152. {
  153. float angle = i * angle_step * 2 * 3.14 / 360;
  154. if (ifZero && SampleSpriteTexture(uv + fixed2(thicknessX * cos(angle), thicknessY * sin(angle))).a == 0)
  155. {
  156. alphaCounter++;
  157. if (alphaCounter >= alphaCount)
  158. {
  159. outline = true;
  160. break;
  161. }
  162. }
  163. else if (!ifZero && SampleSpriteTexture(uv + fixed2(thicknessX * cos(angle), thicknessY * sin(angle))).a > alphaThreshold)
  164. {
  165. outline = true;
  166. break;
  167. }
  168. }
  169. return outline;
  170. }
  171. fixed4 frag(v2f IN) : SV_Target
  172. {
  173. float thicknessX = _Thickness / _MainTex_TexelSize.z;
  174. float thicknessY = _Thickness / _MainTex_TexelSize.w;
  175. fixed4 c = SampleSpriteTexture(IN.texcoord) * IN.color;
  176. c.rgb *= c.a;
  177. fixed alpha;
  178. fixed4 outlineC = fixed4(0, 0, 0, 1);
  179. if (_OutlineEnabled != 0)
  180. {
  181. if (_OutlineMode == 0) // Solid
  182. {
  183. outlineC = _SolidOutline;
  184. if (_ConnectedAlpha != 0)
  185. {
  186. outlineC.a *= _Color.a;
  187. }
  188. outlineC.rgb *= outlineC.a;
  189. }
  190. else if (_OutlineMode == 1) // Gradient
  191. {
  192. float x = IN.texcoord.x;
  193. float y = IN.texcoord.y;
  194. float ratio1 = 0;
  195. float ratio2 = 0;
  196. if (_OutlineShape == 0) // contour
  197. {
  198. if (
  199. ((_OutlinePosition != 2 && _OutlineShape == 1) && c.a != 0 && // inside and frame
  200. (
  201. IN.texcoord.y + thicknessY > 1 ||
  202. IN.texcoord.y - thicknessY < 0 ||
  203. IN.texcoord.x + thicknessX > 1 ||
  204. IN.texcoord.x - thicknessX < 0 ||
  205. CheckOriginalSpriteTexture(IN.texcoord, true)
  206. )
  207. )
  208. ||
  209. ((_OutlinePosition == 2 || _OutlineShape != 1) && c.a == 0 && // outside or contour
  210. CheckOriginalSpriteTexture(IN.texcoord, false)
  211. )
  212. )
  213. {
  214. if (_Angle >= 360)
  215. {
  216. int div = _Angle / 360;
  217. _Angle = (_Angle / 360 - div) * 360;
  218. }
  219. _Angle *= 2 * 3.14 / 360;
  220. ratio1 = (0.5 - x) * cos(_Angle) + (0.5 - y) * sin(_Angle) + 0.5;
  221. ratio2 = (x - 0.5) * cos(_Angle) + (y - 0.5) * sin(_Angle) + 0.5;
  222. ratio1 *= 2 * _Weight;
  223. ratio2 *= 2 * (1 - _Weight);
  224. if (_ConnectedAlpha != 0)
  225. {
  226. _GradientOutline1.a *= _Color.a;
  227. _GradientOutline2.a *= _Color.a;
  228. //outlineC.rgb *= outlineC.a;
  229. }
  230. _GradientOutline1.rgb *= _GradientOutline1.a;
  231. _GradientOutline2.rgb *= _GradientOutline2.a;
  232. outlineC = _GradientOutline1 * ratio1 + _GradientOutline2 * ratio2;
  233. }
  234. }
  235. else if (_OutlineShape == 1) // frame
  236. {
  237. if (IN.texcoord.y + thicknessY > 1 ||
  238. IN.texcoord.y - thicknessY < 0 ||
  239. IN.texcoord.x + thicknessX > 1 ||
  240. IN.texcoord.x - thicknessX < 0)
  241. {
  242. // between down left to up left
  243. if (y * thicknessX - x * thicknessY > 0 &&
  244. y * thicknessX + x * thicknessY - thicknessX < 0 &&
  245. x < 0.5f)
  246. {
  247. ratio1 = 1 - x / thicknessX;
  248. ratio2 = x / thicknessX;
  249. }
  250. // between down left to down right
  251. else if (y * thicknessX - x * thicknessY < 0 &&
  252. y * thicknessX + x * thicknessY - thicknessY < 0 &&
  253. y < 0.5f)
  254. {
  255. ratio1 = 1 - y / thicknessY;
  256. ratio2 = y / thicknessY;
  257. }
  258. // between down right to up right
  259. else if (y * thicknessX - x * thicknessY - thicknessX + thicknessY < 0 &&
  260. y * thicknessX + x * thicknessY - thicknessY > 0 &&
  261. x > 0.5f)
  262. {
  263. ratio1 = (x - 1) / thicknessX + 1;
  264. ratio2 = -(x - 1) / thicknessX;
  265. }
  266. // between up left to up right
  267. else if (y * thicknessX - x * thicknessY - thicknessX + thicknessY > 0 &&
  268. y * thicknessX + x * thicknessY - thicknessX > 0 &&
  269. y > 0.5f)
  270. {
  271. ratio1 = (y - 1) / thicknessY + 1;
  272. ratio2 = -(y - 1) / thicknessY;
  273. }
  274. ratio1 *= 2 * _Weight;
  275. ratio2 *= 2 * (1 - _Weight);
  276. if (_ConnectedAlpha != 0)
  277. {
  278. _GradientOutline1.a *= _Color.a;
  279. _GradientOutline2.a *= _Color.a;
  280. //outlineC.rgb *= outlineC.a;
  281. }
  282. _GradientOutline1.rgb *= _GradientOutline1.a;
  283. _GradientOutline2.rgb *= _GradientOutline2.a;
  284. outlineC = _GradientOutline1 * ratio1 + _GradientOutline2 * ratio2;
  285. }
  286. }
  287. }
  288. else if (_OutlineMode == 2) // Image
  289. {
  290. outlineC = _ImageOutline;
  291. fixed2 frame_coord;
  292. if (_TileMode == 0)
  293. {
  294. frame_coord = IN.texcoord;
  295. }
  296. else if (_TileMode == 1)
  297. {
  298. frame_coord = fixed2
  299. (
  300. _FrameTex_ST.x * IN.texcoord.x * _MainTex_TexelSize.z / _FrameTex_TexelSize.z - _FrameTex_ST.z,
  301. _FrameTex_ST.y * IN.texcoord.y * _MainTex_TexelSize.w / _FrameTex_TexelSize.w - _FrameTex_ST.w
  302. );
  303. if (frame_coord.x > 1)
  304. {
  305. frame_coord = fixed2
  306. (
  307. frame_coord.x - floor(frame_coord.x),
  308. frame_coord.y
  309. );
  310. }
  311. if (frame_coord.y > 1)
  312. {
  313. frame_coord = fixed2
  314. (
  315. frame_coord.x,
  316. frame_coord.y - floor(frame_coord.y)
  317. );
  318. }
  319. }
  320. fixed4 text = tex2D(_FrameTex, frame_coord);
  321. text.rgb *= text.a;
  322. outlineC.rgb *= text.rgb;
  323. outlineC.a *= text.a;
  324. if (_ConnectedAlpha != 0)
  325. {
  326. outlineC.a *= _Color.a;
  327. }
  328. outlineC.rgb *= outlineC.a;
  329. }
  330. if (_OutlineShape == 1) // Frame
  331. {
  332. if (IN.texcoord.y + thicknessY > 1 ||
  333. IN.texcoord.y - thicknessY < 0 ||
  334. IN.texcoord.x + thicknessX > 1 ||
  335. IN.texcoord.x - thicknessX < 0)
  336. {
  337. if (_OutlinePosition == 0 && c.a != 0 && _Thickness > 0)
  338. {
  339. return c;
  340. }
  341. else
  342. {
  343. return outlineC;
  344. }
  345. }
  346. else
  347. {
  348. return c;
  349. }
  350. }
  351. else if (_OutlineShape == 0 && _Thickness > 0) // Contour
  352. {
  353. if ((_OutlinePosition != 2 && _OutlineShape == 1) && c.a != 0 && // inside and frame
  354. (
  355. IN.texcoord.y + thicknessY > 1 ||
  356. IN.texcoord.y - thicknessY < 0 ||
  357. IN.texcoord.x + thicknessX > 1 ||
  358. IN.texcoord.x - thicknessX < 0 ||
  359. CheckOriginalSpriteTexture(IN.texcoord, true)
  360. )
  361. )
  362. {
  363. return outlineC;
  364. }
  365. else if ((_OutlinePosition == 2 || _OutlineShape != 1) && c.a == 0 && // outside orcontour
  366. (
  367. CheckOriginalSpriteTexture(IN.texcoord, false)
  368. )
  369. )
  370. {
  371. return outlineC;
  372. }
  373. else
  374. {
  375. return c;
  376. }
  377. }
  378. else
  379. {
  380. return c;
  381. }
  382. }
  383. else
  384. {
  385. return c;
  386. }
  387. return c;
  388. //return c;
  389. }
  390. ENDCG
  391. }
  392. }
  393. }