Unity 2D图片添加加外边框Shader
在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相关推荐
- Unity 2D图片外轮廓描边和内发光的Shader实现
很长时间没有写博客了,一方面Sebastian大佬正在更新程序生成星球的教程,所以想等到大佬更新接近尾声的时候开始那个教程的分享.最近主要是在工作之余补一补Unityshader的基础知识,然后正好在 ...
- 【游戏开发创新】Unity 2D图片任意形状破碎碎裂效果,以此纪念我的牙光荣牺牲
文章目录 一.前言 二.效果演示 三.Demo工程下载 四.操作步骤 1.牙图片:SrpiteRenderer 2.碎裂:Explodable 3.多边形碰撞体组件:PolygonCollider2D ...
- Unity 2D图片的3D效果(1)——阴影
项目为方便编辑地图,使用的是Unity自带的Tilemap功能.因为使用的是俯视视角,拼好第一个地图后发现2D图片展现的效果太平了,地面和障碍物很难分辨.所以才有了"把2d图片展现出3d效果 ...
- aspose.cell 设置样式 java_Aspose.Cell怎么单独给表格加外边框?
问题描述 在做导出报表时候,想给导出的表格做个边框 问题出现的环境背景及自己尝试过哪些方法 但是看到aspose.cell 好像都是一个单元格一设置,没有对于整个表格设置的 相关代码 // 请把代码文 ...
- html给table加外边框,html如何给table表单加边框
表格边框 如↑图,这个时候我们发现,css中的border其实就是给表格加了一个外边框而已 五.border-collapse: collapse 边框合并,该属性设置表格的边框是否被合并为一个单一的 ...
- html圆形图片怎么加白边框,带图片,带文字,有白边框的这种图片怎么制作的?...
这种"留白图文"可以用手机APP快速制作,用现成的文字模板,或者是自己加字,加图案都OK.比如:下面同样一张图片和文字,加上留白后,只需调整照片位置就能做出多种图文效果. 1.横版 ...
- Unity给图片添加点击事件
写在前面 实现目标:点击图片,可以弹出一个Panel界面. 实现方法:使用组件Event Trigger给图片添加一个Click事件,并将Click需要实现的功能代码绑定到该图片. 实现步骤 1.在i ...
- html给table加外边框,如何给table添加边框
1.开发环境 vue+vant 2.电脑系统 windows10专业版 3.在开发的过程中,我们经常会使用到表格组件,但是我们会发现在vant中没有表格组件,这个时候我们可以选择自己手写一个table ...
- html圆形图片怎么加白边框,SwiftUI圆形图片制作示例_如何设置图片为圆形并加边框阴影效果...
这个教程将使用SwiftUI制作一个圆形图片,并给图片设置边框与阴影效果,我们以前的swift使用的是UIImageView这个对象来加载图片,这是UIkit里面的类,而今天的SwiftUI加载图片, ...
- 菜鸟也能当PS高手!PhotoWorks为你的图片添加漂亮的边框(教程+下载)
是否看过别人的网站或贴图上的图片有那么一个漂亮的边框,使整张图片都美观了?他们是怎么做到的? 给图片加边框对于PS高手来说是小菜一碟而已,但对于大多数的一般的朋友来说是一件很难的事情,为了这个去学Ph ...
最新文章
- 插入顶部_轻巧的衣领插入技术
- WSS 3.0 在默认的情况下不存在IRM的protector.
- python图形编程复选按钮和单选按钮详细说明_Python_tkinter_单选框(Radiobutton)与复选框(Checkbutton)...
- [Xcode 实际操作]四、常用控件-(5)UILabel文本标签自定义文字样式
- 数据库开发——MySQL——简单介绍和安装
- ajax返回list前台遍历_List、set集合接口分析
- 你准备好了吗,江湖来了
- 使用linux实验总结及心得,实验心得
- pytorch学习笔记(三):线性回归
- 手机怎么安装py thon_Python调试器– Py​​thon pdb
- 安装高版本的java_运行“需要Java 11或更高版本”的Visual Studio代码。请下载并安装最新的JDK”...
- HEVC播放器出炉,迅雷看看支持H.265
- 8分钟教你学会局域网邮箱服务器搭建
- 【笔记】wincap收集并统计网络流量
- 2019 美团校招笔试题 外卖满减
- 大学生计算机装机配置作业,不愧是计算机专业的大学生,自己写配置来装机,万元电脑真霸气...
- python基础语法(十一)——测试代码
- iPhone开发中的技巧整理(二)
- 明翰Docker笔记V0.1(持续更新)
- VMware Fusion5激活Win7