2D图片的描边

第一种 Sprite 外边框

原理是找到边缘像素,然后设置颜色,边缘像素的特点是像素的八个方向的邻像素不全是透明或者不全是不透明,这样的像素就是边缘上的像素,下面是找到的shader源码,很简单

Shader "Custom/Sprite Outline"
{
	Properties
	{
		_MainTex ("Sprite Texture", 2D) = "white" {}
		_Color ("Tint", Color) = (1,1,1,1)
		
		_OutlineThickness("Outline Thickness", Range (0.0, 0.1)) = 0.0
		_OutlineColor ("Outline Color", Color) = (1,1,1,1)
	}

	SubShader
	{
		Tags
		{ 
			"Queue"="Transparent" 
			"IgnoreProjector"="True" 
			"RenderType"="Transparent" 
			"PreviewType"="Plane"
			"CanUseSpriteAtlas"="True"
		}

		Cull Off
		Lighting Off
		ZWrite Off
		Blend One OneMinusSrcAlpha

		Pass
		{
		CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma multi_compile _ PIXELSNAP_ON
			#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;
			sampler2D _MainTex;
			
			fixed4 _OutlineColor;
			fixed _OutlineThickness;

			v2f vert(appdata_t IN)
			{
				v2f OUT;
				OUT.vertex = UnityObjectToClipPos(IN.vertex);
				OUT.texcoord = IN.texcoord;
				OUT.color = IN.color * _Color;
				return OUT;
			}

			fixed4 SampleSpriteTexture (float2 uv)
			{
				fixed4 color = tex2D (_MainTex, uv);
				return color;
			}

			fixed4 frag(v2f IN) : COLOR
			{
				fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color;
				c.rgb *= c.a;
				
				fixed4 outlineC = _OutlineColor;
                outlineC.rgb *= outlineC.a;
                //outlineC.a *= ceil(c.a);

                if (c.a == 0.0)
				{
                    fixed upAlpha = SampleSpriteTexture ( IN.texcoord + fixed2(0, _OutlineThickness)).a;
                    fixed downAlpha = SampleSpriteTexture ( IN.texcoord - fixed2(0, _OutlineThickness)).a;
                    fixed rightAlpha = SampleSpriteTexture ( IN.texcoord + fixed2(_OutlineThickness, 0)).a;
                    fixed leftAlpha = SampleSpriteTexture ( IN.texcoord - fixed2(_OutlineThickness, 0)).a;
                    
                    fixed upRightAlpha = SampleSpriteTexture ( IN.texcoord - fixed2(_OutlineThickness, _OutlineThickness)).a;
                    fixed upLeftAlpha = SampleSpriteTexture ( IN.texcoord - fixed2(_OutlineThickness, -_OutlineThickness)).a;
                    fixed downRightAlpha = SampleSpriteTexture ( IN.texcoord - fixed2(-_OutlineThickness, _OutlineThickness)).a;
                    fixed downLeftAlpha = SampleSpriteTexture ( IN.texcoord - fixed2(-_OutlineThickness, -_OutlineThickness)).a;
				
                
				    if (upAlpha != 0.0|| downAlpha != 0.0 || rightAlpha != 0.0 || leftAlpha != 0.0 || upRightAlpha != 0.0 || upLeftAlpha != 0.0 || downLeftAlpha != 0.0 || downRightAlpha != 0.0)
				        return outlineC;    
				}
				
				return c;
			}
		ENDCG
		}
	}
}
第二种 UI图片外边框

UGUI已经开源了,特意扒了一下源码,outline组件中是通过ModifyMesh接口改变的顶点偏移,然后outline组件是继承自shadow组件,可以说是outline和shadow实现原理一样的,就是把图像进行偏移然后设置颜色,然后在渲染原图,也就是这个效果需要渲染两次,这面是顶点处理的回调函数

 public override void ModifyMesh(VertexHelper vh)
 {
     if (!IsActive())
         return;

     var verts = ListPool<UIVertex>.Get();
     vh.GetUIVertexStream(verts);

     var neededCpacity = verts.Count * 5;
     if (verts.Capacity < neededCpacity)
         verts.Capacity = neededCpacity;

     var start = 0;
     var end = verts.Count;
     ApplyShadowZeroAlloc(verts, effectColor, start, verts.Count, effectDistance.x, effectDistance.y);

     start = end;
     end = verts.Count;
     ApplyShadowZeroAlloc(verts, effectColor, start, verts.Count, effectDistance.x, -effectDistance.y);

     start = end;
     end = verts.Count;
     ApplyShadowZeroAlloc(verts, effectColor, start, verts.Count, -effectDistance.x, effectDistance.y);

     start = end;
     end = verts.Count;
     ApplyShadowZeroAlloc(verts, effectColor, start, verts.Count, -effectDistance.x, -effectDistance.y);

     vh.Clear();
     vh.AddUIVertexTriangleStream(verts);
     ListPool<UIVertex>.Release(verts);
 }

相关推荐

  1. 2D图片

    2024-06-10 16:56:03       10 阅读
  2. 【CSS】实现文字

    2024-06-10 16:56:03       16 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-10 16:56:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-10 16:56:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-10 16:56:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-10 16:56:03       18 阅读

热门阅读

  1. 使用vue3+ts封装一个Switch开关组件

    2024-06-10 16:56:03       9 阅读
  2. 每个寒暑假学习一项新技能

    2024-06-10 16:56:03       11 阅读
  3. python小tips

    2024-06-10 16:56:03       8 阅读
  4. git命令

    git命令

    2024-06-10 16:56:03      8 阅读
  5. Python之Pandas详解

    2024-06-10 16:56:03       9 阅读
  6. 04-4.2.3 KMP 算法求 next 数组

    2024-06-10 16:56:03       13 阅读
  7. 【系统学C++】一、从C语言到C++(一)

    2024-06-10 16:56:03       11 阅读
  8. 关于MySQL 中的全局事务标识符GTID

    2024-06-10 16:56:03       9 阅读
  9. C# - 委托与事件

    2024-06-10 16:56:03       6 阅读
  10. 如何进行《我的世界》基于Spigot的插件开发

    2024-06-10 16:56:03       12 阅读