在Unity的开发当中,有时会有为图片添加外边框的需求,在资源商店有Demo:2D Sprite Outline
我们根据上面的Demo,做如下整理
1、新建Shader,代码如下:

Shader "Custom/SpritesOutline"
{Properties{[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}_Color ("Main texture Tint", Color) = (1,1,1,1)[Header(General Settings)][MaterialToggle] _OutlineEnabled ("Outline Enabled", Float) = 1[MaterialToggle] _ConnectedAlpha ("Connected Alpha", Float) = 0[HideInInspector] _AlphaThreshold ("Alpha clean", Range (0, 1)) = 0_Thickness ("Width (Max recommended 100)", float) = 10[KeywordEnum(Solid, Gradient, Image)] _OutlineMode("Outline mode", Float) = 0[KeywordEnum(Contour, Frame)] _OutlineShape("Outline shape", Float) = 0[KeywordEnum(Inside under sprite, Inside over sprite, Outside)] _OutlinePosition("Outline Position (Frame Only)", Float) = 0[Header(Solid Settings)]_SolidOutline ("Outline Color Base", Color) = (1,1,1,1)[Header(Gradient Settings)]_GradientOutline1 ("Outline Color 1", Color) = (1,1,1,1)_GradientOutline2 ("Outline Color 2", Color) = (1,1,1,1)_Weight ("Weight", Range (0, 1)) = 0.5_Angle ("Gradient Angle (General gradient Only)", float) = 45//[KeywordEnum(General, Frame directed)] _FrameMode("Frame Mode (Frame Only)", Float) = 0[Header(Image Settings)]_FrameTex ("Frame Texture", 2D) = "white" {}_ImageOutline ("Outline Color Base", Color) = (1,1,1,1)[KeywordEnum(Stretch, Tile)] _TileMode("Frame mode", Float) = 0}SubShader{Tags{ "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane""CanUseSpriteAtlas"="True"}Cull OffLighting OffZWrite OffBlend One OneMinusSrcAlphaPass{CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma multi_compile _ PIXELSNAP_ON#pragma exclude_renderers d3d11_9x#include "UnityCG.cginc"struct appdata_t{float4 vertex   : POSITION;float4 color    : COLOR;float2 texcoord : TEXCOORD0;};struct v2f{float4 vertex   : SV_POSITION;fixed4 color    : COLOR;float2 texcoord  : TEXCOORD0;};fixed4 _Color;fixed _Thickness;fixed _OutlineEnabled;fixed _ConnectedAlpha;fixed _OutlineShape;fixed _OutlinePosition;fixed _OutlineMode;fixed4 _SolidOutline;fixed4 _GradientOutline1;fixed4 _GradientOutline2;fixed _Weight;fixed _AlphaThreshold;fixed _Angle;//fixed _FrameMode;fixed4 _ImageOutline;fixed _TileMode;v2f vert(appdata_t IN){v2f OUT;OUT.vertex = UnityObjectToClipPos(IN.vertex);OUT.texcoord = IN.texcoord;OUT.color = IN.color * _Color;#ifdef PIXELSNAP_ONOUT.vertex = UnityPixelSnap (OUT.vertex);#endifreturn OUT;}sampler2D _MainTex;sampler2D _AlphaTex;float _AlphaSplitEnabled;uniform float4 _MainTex_TexelSize;sampler2D _FrameTex;uniform float4 _FrameTex_TexelSize;uniform float4 _FrameTex_ST;fixed4 SampleSpriteTexture (float2 uv){float2 offsets;if((_OutlinePosition != 2 && _OutlineShape == 1) || _OutlineEnabled == 0) // not outside and frame{offsets = float2(0, 0);}else{offsets = float2(_Thickness * 2, _Thickness * 2);}float2 bigsize = float2(_MainTex_TexelSize.z, _MainTex_TexelSize.w);float2 smallsize = float2(_MainTex_TexelSize.z - offsets.x, _MainTex_TexelSize.w - offsets.y);float2 uv_changed = float2(uv.x * bigsize.x / smallsize.x - 0.5 * offsets.x / smallsize.x,uv.y * bigsize.y / smallsize.y - 0.5 * offsets.y / smallsize.y);if(uv_changed.x < 0 || uv_changed.x > 1 || uv_changed.y < 0 || uv_changed.y > 1){return float4(0, 0, 0, 0);}fixed4 color = tex2D (_MainTex, uv_changed);#if UNITY_TEXTURE_ALPHASPLIT_ALLOWEDif (_AlphaSplitEnabled)color.a = tex2D (_AlphaTex, uv).r;
#endif //UNITY_TEXTURE_ALPHASPLIT_ALLOWEDreturn color;}bool CheckOriginalSpriteTexture (float2 uv, bool ifZero){float thicknessX = _Thickness / _MainTex_TexelSize.z;float thicknessY = _Thickness / _MainTex_TexelSize.w;int steps = 100;float angle_step = 360.0 / steps;float alphaThreshold = _AlphaThreshold / 10;float alphaCount = _AlphaThreshold * 10;// check if the basic points has an alpha to speed up the process and not use the for loopbool outline = false;float alphaCounter = 0;if(ifZero){}else{outline =    SampleSpriteTexture(uv + fixed2(0, +thicknessY)).a > alphaThreshold ||SampleSpriteTexture(uv + fixed2(0, -thicknessY)).a > alphaThreshold ||SampleSpriteTexture(uv + fixed2(+thicknessX, 0)).a > alphaThreshold ||SampleSpriteTexture(uv + fixed2(-thicknessX, 0)).a > alphaThreshold ||SampleSpriteTexture(uv + fixed2(+thicknessX * cos (3.14 / 4), -thicknessY * sin (3.14 / 4))).a > alphaThreshold ||SampleSpriteTexture(uv + fixed2(-thicknessX * cos (3.14 / 4), +thicknessY * sin (3.14 / 4))).a > alphaThreshold ||SampleSpriteTexture(uv + fixed2(-thicknessX * cos (3.14 / 4), -thicknessY * sin (3.14 / 4))).a > alphaThreshold ||SampleSpriteTexture(uv + fixed2(+thicknessX * cos (3.14 / 4), +thicknessY * sin (3.14 / 4))).a > alphaThreshold;}if(outline) return outline;for(int i = 0; i < steps; i++) // high number and not a variable to avoid stupid compiler bugs{float angle = i * angle_step * 2 * 3.14 / 360;if(ifZero && SampleSpriteTexture(uv + fixed2(thicknessX * cos(angle), thicknessY * sin(angle))).a == 0){alphaCounter++;if(alphaCounter >= alphaCount){outline = true;break;}}else if(!ifZero && SampleSpriteTexture(uv + fixed2(thicknessX * cos(angle), thicknessY * sin(angle))).a > alphaThreshold){outline = true;break;}}return outline;}fixed4 frag(v2f IN) : SV_Target{float thicknessX = _Thickness / _MainTex_TexelSize.z;float thicknessY = _Thickness / _MainTex_TexelSize.w;fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;c.rgb *= c.a;fixed alpha;fixed4 outlineC = fixed4(0, 0, 0, 1);if(_OutlineEnabled != 0){if(_OutlineMode == 0) // Solid{outlineC = _SolidOutline;if(_ConnectedAlpha != 0){outlineC.a *= _Color.a;}outlineC.rgb *= outlineC.a;}else if(_OutlineMode == 1) // Gradient{float x = IN.texcoord.x;float y = IN.texcoord.y;float ratio1 = 0;float ratio2 = 0;if(_OutlineShape == 0) // contour{if(((_OutlinePosition != 2 && _OutlineShape == 1) && c.a != 0 &&  // inside and frame(IN.texcoord.y + thicknessY > 1 || IN.texcoord.y - thicknessY < 0 || IN.texcoord.x + thicknessX > 1 || IN.texcoord.x - thicknessX < 0 ||CheckOriginalSpriteTexture(IN.texcoord, true)))||((_OutlinePosition == 2 || _OutlineShape != 1) && c.a == 0 &&   // outside or contourCheckOriginalSpriteTexture(IN.texcoord, false))){if(_Angle >= 360){int div = _Angle / 360;_Angle = (_Angle / 360 - div) * 360;}_Angle *= 2 * 3.14 / 360;ratio1 = (0.5 - x) * cos(_Angle) + (0.5 - y) * sin(_Angle) + 0.5;ratio2 = (x - 0.5) * cos(_Angle) + (y - 0.5) * sin(_Angle) + 0.5;ratio1 *= 2 * _Weight;ratio2 *= 2 * (1 - _Weight);if(_ConnectedAlpha != 0){_GradientOutline1.a *= _Color.a;_GradientOutline2.a *= _Color.a;//outlineC.rgb *= outlineC.a;}_GradientOutline1.rgb *= _GradientOutline1.a;_GradientOutline2.rgb *= _GradientOutline2.a;outlineC = _GradientOutline1 * ratio1 + _GradientOutline2 * ratio2;}}else if(_OutlineShape == 1) // frame{if( IN.texcoord.y + thicknessY > 1 ||IN.texcoord.y - thicknessY < 0 ||IN.texcoord.x + thicknessX > 1 ||IN.texcoord.x - thicknessX < 0){// between down left to up leftif (y * thicknessX - x * thicknessY > 0 &&y * thicknessX + x * thicknessY - thicknessX < 0 &&x < 0.5f){ratio1 = 1 - x / thicknessX;ratio2 = x / thicknessX;}// between down left to down rightelse if (y * thicknessX - x * thicknessY < 0 &&y * thicknessX + x * thicknessY - thicknessY < 0 &&y < 0.5f){ratio1 = 1 - y / thicknessY;ratio2 = y / thicknessY;}// between down right to up rightelse if (y * thicknessX - x * thicknessY - thicknessX + thicknessY < 0 &&y * thicknessX + x * thicknessY - thicknessY > 0 &&x > 0.5f){ratio1 = (x - 1) / thicknessX + 1;ratio2 = -(x - 1) / thicknessX;}// between up left to up rightelse if (y * thicknessX - x * thicknessY - thicknessX + thicknessY > 0 &&y * thicknessX + x * thicknessY - thicknessX > 0 &&y > 0.5f){ratio1 = (y - 1) / thicknessY + 1;ratio2 = -(y - 1) / thicknessY;}ratio1 *= 2 * _Weight;ratio2 *= 2 * (1 - _Weight);if(_ConnectedAlpha != 0){_GradientOutline1.a *= _Color.a;_GradientOutline2.a *= _Color.a;//outlineC.rgb *= outlineC.a;}_GradientOutline1.rgb *= _GradientOutline1.a;_GradientOutline2.rgb *= _GradientOutline2.a;outlineC = _GradientOutline1 * ratio1 + _GradientOutline2 * ratio2;}}}else if(_OutlineMode == 2) // Image{outlineC = _ImageOutline;fixed2 frame_coord;if(_TileMode == 0){frame_coord = IN.texcoord;}else if(_TileMode == 1){frame_coord = fixed2(_FrameTex_ST.x * IN.texcoord.x * _MainTex_TexelSize.z / _FrameTex_TexelSize.z - _FrameTex_ST.z,_FrameTex_ST.y * IN.texcoord.y * _MainTex_TexelSize.w / _FrameTex_TexelSize.w - _FrameTex_ST.w);if(frame_coord.x > 1){frame_coord = fixed2(frame_coord.x - floor(frame_coord.x),frame_coord.y);}if(frame_coord.y > 1){frame_coord = fixed2(frame_coord.x,frame_coord.y - floor(frame_coord.y));}}fixed4 text = tex2D(_FrameTex, frame_coord);text.rgb *= text.a;outlineC.rgb *= text.rgb;outlineC.a *= text.a;if(_ConnectedAlpha != 0){outlineC.a *= _Color.a;}outlineC.rgb *= outlineC.a;}if(_OutlineShape == 1) // Frame{if( IN.texcoord.y + thicknessY > 1 ||IN.texcoord.y - thicknessY < 0 ||IN.texcoord.x + thicknessX > 1 ||IN.texcoord.x - thicknessX < 0){if(_OutlinePosition == 0 && c.a != 0 && _Thickness > 0){return c;}else{return outlineC;}}else{return c;}}else if(_OutlineShape == 0 && _Thickness > 0) // Contour{if((_OutlinePosition != 2 && _OutlineShape == 1) && c.a != 0 && // inside and frame(IN.texcoord.y + thicknessY > 1 ||IN.texcoord.y - thicknessY < 0 ||IN.texcoord.x + thicknessX > 1 ||IN.texcoord.x - thicknessX < 0 || CheckOriginalSpriteTexture(IN.texcoord, true))){return outlineC;}else if((_OutlinePosition == 2 || _OutlineShape != 1) && c.a == 0 && // outside orcontour(CheckOriginalSpriteTexture(IN.texcoord, false))){return outlineC;}else{return c;}}else{return c;}}else{return c;}return c;//return c;}ENDCG}}
}

2、创建材质,选择刚刚创建的Shader

3、为图片添加材质:

4、效果如下:

5、控制边框的显示与隐藏,只要控制边框的宽度即可。代码如下:

public class OutlineController : MonoBehaviour
{//2D图片边框材质public Material outLineMaterial;/// <summary>/// 显示边框/// </summary>private void ShowOutline(){outLineMaterial.SetFloat("_Thickness", 10);}/// <summary>/// 隐藏边框/// </summary>private void HideOutline(){outLineMaterial.SetFloat("_Thickness", 0);}
}

Unity 2D图片添加加外边框Shader相关推荐

  1. Unity 2D图片外轮廓描边和内发光的Shader实现

    很长时间没有写博客了,一方面Sebastian大佬正在更新程序生成星球的教程,所以想等到大佬更新接近尾声的时候开始那个教程的分享.最近主要是在工作之余补一补Unityshader的基础知识,然后正好在 ...

  2. 【游戏开发创新】Unity 2D图片任意形状破碎碎裂效果,以此纪念我的牙光荣牺牲

    文章目录 一.前言 二.效果演示 三.Demo工程下载 四.操作步骤 1.牙图片:SrpiteRenderer 2.碎裂:Explodable 3.多边形碰撞体组件:PolygonCollider2D ...

  3. Unity 2D图片的3D效果(1)——阴影

    项目为方便编辑地图,使用的是Unity自带的Tilemap功能.因为使用的是俯视视角,拼好第一个地图后发现2D图片展现的效果太平了,地面和障碍物很难分辨.所以才有了"把2d图片展现出3d效果 ...

  4. aspose.cell 设置样式 java_Aspose.Cell怎么单独给表格加外边框?

    问题描述 在做导出报表时候,想给导出的表格做个边框 问题出现的环境背景及自己尝试过哪些方法 但是看到aspose.cell 好像都是一个单元格一设置,没有对于整个表格设置的 相关代码 // 请把代码文 ...

  5. html给table加外边框,html如何给table表单加边框

    表格边框 如↑图,这个时候我们发现,css中的border其实就是给表格加了一个外边框而已 五.border-collapse: collapse 边框合并,该属性设置表格的边框是否被合并为一个单一的 ...

  6. html圆形图片怎么加白边框,带图片,带文字,有白边框的这种图片怎么制作的?...

    这种"留白图文"可以用手机APP快速制作,用现成的文字模板,或者是自己加字,加图案都OK.比如:下面同样一张图片和文字,加上留白后,只需调整照片位置就能做出多种图文效果. 1.横版 ...

  7. Unity给图片添加点击事件

    写在前面 实现目标:点击图片,可以弹出一个Panel界面. 实现方法:使用组件Event Trigger给图片添加一个Click事件,并将Click需要实现的功能代码绑定到该图片. 实现步骤 1.在i ...

  8. html给table加外边框,如何给table添加边框

    1.开发环境 vue+vant 2.电脑系统 windows10专业版 3.在开发的过程中,我们经常会使用到表格组件,但是我们会发现在vant中没有表格组件,这个时候我们可以选择自己手写一个table ...

  9. html圆形图片怎么加白边框,SwiftUI圆形图片制作示例_如何设置图片为圆形并加边框阴影效果...

    这个教程将使用SwiftUI制作一个圆形图片,并给图片设置边框与阴影效果,我们以前的swift使用的是UIImageView这个对象来加载图片,这是UIkit里面的类,而今天的SwiftUI加载图片, ...

  10. 菜鸟也能当PS高手!PhotoWorks为你的图片添加漂亮的边框(教程+下载)

    是否看过别人的网站或贴图上的图片有那么一个漂亮的边框,使整张图片都美观了?他们是怎么做到的? 给图片加边框对于PS高手来说是小菜一碟而已,但对于大多数的一般的朋友来说是一件很难的事情,为了这个去学Ph ...

最新文章

  1. 插入顶部_轻巧的衣领插入技术
  2. WSS 3.0 在默认的情况下不存在IRM的protector.
  3. python图形编程复选按钮和单选按钮详细说明_Python_tkinter_单选框(Radiobutton)与复选框(Checkbutton)...
  4. [Xcode 实际操作]四、常用控件-(5)UILabel文本标签自定义文字样式
  5. 数据库开发——MySQL——简单介绍和安装
  6. ajax返回list前台遍历_List、set集合接口分析
  7. 你准备好了吗,江湖来了
  8. 使用linux实验总结及心得,实验心得
  9. pytorch学习笔记(三):线性回归
  10. 手机怎么安装py thon_Python调试器– Py​​thon pdb
  11. 安装高版本的java_运行“需要Java 11或更高版本”的Visual Studio代码。请下载并安装最新的JDK”...
  12. HEVC播放器出炉,迅雷看看支持H.265
  13. 8分钟教你学会局域网邮箱服务器搭建
  14. 【笔记】wincap收集并统计网络流量
  15. 2019 美团校招笔试题 外卖满减
  16. 大学生计算机装机配置作业,不愧是计算机专业的大学生,自己写配置来装机,万元电脑真霸气...
  17. python基础语法(十一)——测试代码
  18. iPhone开发中的技巧整理(二)
  19. 明翰Docker笔记V0.1(持续更新)
  20. VMware Fusion5激活Win7

热门文章

  1. 经济基础知识(中级)【6】
  2. 巧用Python爬取QQ空间好友信息,生成词云
  3. win10升级助手_快升级!win10精简版不到10G,比win7还干净流畅,无需更新!
  4. WEB测试工具---死链接检测工具xenu
  5. 读书笔记5.2——《让数字说话:审计,就这么简单》:孙含晖
  6. html源码(html+css)
  7. 进击zheng项目zheng-umps-server
  8. 微信小程序中输出大于号和小于号
  9. 【工具推荐】进程查看管理工具——Process Explorer
  10. matlab神经网络工具箱的使用