[默认管线]2D图羽化内外发光Shader

这个是昨天接到的一个需求:

其实说白了就是想做实时抠像,然后内外边缘给到羽化,就这么一个效果;

如果是给模型做羽化,在不用Bloom的情况下可以用(1-F)去做;

2D图片的话就不能这么做了;

核心算法,复制粘贴:


			float4 Outline(sampler2D mainTex, float2 uv, fixed4 color, float width, float weight, out float alpha)
			{
				int sampleTimes = 0;
				float4 ret = float4(0, 0, 0, 0);
				float step = 8 / _OutlineAccuracy;
				for (float i = -16; i <= 16; i += step)
				{
					for (float j = -16; j <= 16; j += step)
					{
						float2 offset = 0.1 * float2(i, j) / 32 * width;
						float2 offsetUV = saturate(uv + offset);
						ret += tex2D(mainTex, offsetUV);
						++sampleTimes;
					}
				}

				ret = lerp(float4(0, 0, 0, 0), ret / sampleTimes, weight);
				ret.rgb = color.rgb;
				fixed4 c = tex2D(mainTex, uv);
				ret.rgb *= (ret.a - c.a) * 3;
				ret = lerp(ret, c, (c.a > _OutlineMaskAlpha ? 1 : c.a));

				float2 rotator1 = RotateAndScaleUV(uv, _OutlineFlowSpeed1, _MaskUVScale1);
				float2 rotator2 = RotateAndScaleUV(uv, _OutlineFlowSpeed2, _MaskUVScale2);

				alpha = clamp((tex2D(_MaskTexture1, rotator1).a * 0.5 + tex2D(_MaskTexture2, rotator2).a * 0.5), 0, 1);
				return ret;
			}

我们来看下最后的效果:

是不是比较接近了,全部代码如下(未做优化,可以自行合并那个方法):

Shader "AnimatedSpriteOutline/Outline Light"
{
	Properties
	{
		_MainTex("_MainTex", 2D) = "white" {}
		_MaskTexture1("_MaskTexture1", 2D) = "white" {}
		_MaskTexture2("_MaskTexture2", 2D) = "white" {}
		_MaskUVScale1("_MaskUVScale1", Range(0, 2)) = 0
		_MaskUVScale2("_MaskUVScale2", Range(0, 2)) = 0
		_OutlineColor1("_OutlineColor1", COLOR) = (1, 1, 1, 1)
		_OutlineColor2("_OutlineColor2", COLOR) = (1, 1, 1, 1)
		_OutlineWidth1("_OutlineWidth1", Range(0, 1)) = 0
		_OutlineWidth2("_OutlineWidth2", Range(0, 1)) = 0
		_OutlineWeight1("_OutlineWeight1", Range(0, 4)) = 0
		_OutlineWeight2("_OutlineWeight2", Range(0, 4)) = 0
		_OutlineFlowSpeed1("_OutlineFlowSpeed1", Range(0, 3)) = 0
		_OutlineFlowSpeed2("_OutlineFlowSpeed2", Range(0, 3)) = 0
		_OutlineAccuracy("_OutlineAccuracy", Range(1, 16)) = 8
		_OutlineMaskAlpha("_OutlineMaskAlpha", Range(0, 1)) = 0
		_BloomFallOff("_BloomFallOff", Range(0, 1)) = 1
		_Nei("内发光",Range(0,4))=1
		//_Nei0("内宽",Range(0,4))=1
	}

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

		ZWrite Off
		Blend SrcAlpha OneMinusSrcAlpha
		Cull Off 

		Pass
		{
			CGPROGRAM
			#include "UnityCG.cginc"
			#pragma vertex vert
			#pragma fragment frag

			struct appdata_t
			{
				float4 vertex : POSITION;
				fixed4 color  : COLOR;
				float2 uv     : TEXCOORD0;
			};

			struct v2f
			{
				float4 position : SV_POSITION;
				fixed4 color    : COLOR;
				float2 uv       : TEXCOORD0;
			};

			sampler2D _MainTex;
			sampler2D _MaskTexture1;
			sampler2D _MaskTexture2;
			fixed4 _OutlineColor1;
			fixed4 _OutlineColor2;
			float _MaskUVScale1;
			float _MaskUVScale2;
			float _OutlineWidth1;
			float _OutlineWidth2;
			float _OutlineWeight1;
			float _OutlineWeight2;
			float _OutlineFlowSpeed1;
			float _OutlineFlowSpeed2;
			float _OutlineAccuracy;
			float _OutlineMaskAlpha;
			float _BloomFallOff;
			float alpha1;
			float alpha2;
			float _Nei;float _Nei0;

			float2 RotateAndScaleUV(float2 uv, float speed, float scale)
			{
				float cosValue = cos(_Time.y * speed);
				float sinValue = sin(_Time.y * speed);
				return mul(uv - float2(0.5, 0.5), float2x2(cosValue, -sinValue, sinValue, cosValue)) * scale + float2(0.5, 0.5);
			}

			float4 Outline(sampler2D mainTex, float2 uv, fixed4 color, float width, float weight, out float alpha)
			{
				int sampleTimes = 0;
				float4 ret = float4(0, 0, 0, 0);
				float step = 8 / _OutlineAccuracy;
				for (float i = -16; i <= 16; i += step)
				{
					for (float j = -16; j <= 16; j += step)
					{
						float2 offset = 0.1 * float2(i, j) / 32 * width;
						float2 offsetUV = saturate(uv + offset);
						ret += tex2D(mainTex, offsetUV);
						++sampleTimes;
					}
				}

				ret = lerp(float4(0, 0, 0, 0), ret / sampleTimes, weight);
				ret.rgb = color.rgb;
				fixed4 c = tex2D(mainTex, uv);
				ret.rgb *= (ret.a - c.a) * 3;
				ret = lerp(ret, c, (c.a > _OutlineMaskAlpha ? 1 : c.a));

				float2 rotator1 = RotateAndScaleUV(uv, _OutlineFlowSpeed1, _MaskUVScale1);
				float2 rotator2 = RotateAndScaleUV(uv, _OutlineFlowSpeed2, _MaskUVScale2);

				alpha = clamp((tex2D(_MaskTexture1, rotator1).a * 0.5 + tex2D(_MaskTexture2, rotator2).a * 0.5), 0, 1);
				return ret;
			}


			float4 OutlineNei(sampler2D mainTex, float2 uv, fixed4 color, float width, float weight, out float alpha)
			{
				int sampleTimes = 0;
				float4 ret = float4(0, 0, 0, 0);
				float step = 8 / _OutlineAccuracy;
				for (float i = -16; i <= 16; i += step)
				{
					for (float j = -16; j <= 16; j += step)
					{
						float2 offset = 0.1 * float2(i, j) / 32 * width;
						float2 offsetUV = saturate(uv + offset);
						ret += tex2D(mainTex, offsetUV);
						++sampleTimes;
					}
				}

				ret = lerp(float4(0, 0, 0, 0), ret / sampleTimes, weight);
				ret.rgb = color.rgb;
				fixed4 c = tex2D(mainTex, uv);
				ret.rgb *= (ret.a - c.a) * 3;
				ret = lerp(ret, c, 1-(c.a > _OutlineMaskAlpha ? 1 : c.a));

				float2 rotator1 = RotateAndScaleUV(uv, _OutlineFlowSpeed1, _MaskUVScale1);
				float2 rotator2 = RotateAndScaleUV(uv, _OutlineFlowSpeed2, _MaskUVScale2);

				alpha = clamp((tex2D(_MaskTexture1, rotator1).a * 0.5 + tex2D(_MaskTexture2, rotator2).a * 0.5), 0, 1);
				return ret;
			}

			v2f vert(appdata_t i)
			{
				v2f o;
				o.position = UnityObjectToClipPos(i.vertex);
				o.uv = i.uv;
				o.color = i.color;
				return o;
			}

			float4 frag (v2f i) : COLOR
			{
				float4 outline1 = Outline(_MainTex, i.uv, _OutlineColor1, _OutlineWidth1, _OutlineWeight1, alpha1);
				float4 outline2 = Outline(_MainTex, i.uv, _OutlineColor2, _OutlineWidth2, _OutlineWeight2, alpha2);
				float4 outline03 = OutlineNei(_MainTex, i.uv, _OutlineColor1, _OutlineWidth1, _Nei0, alpha1);
				float4 outline3 = OutlineNei(_MainTex, i.uv, _OutlineColor2, _OutlineWidth2, _Nei, alpha2);

				float4 c = tex2D(_MainTex, i.uv);
				outline1.a = clamp(alpha1 * clamp(outline1.a - c.a, 0, 1), 0, 1);
				outline2.a = clamp(alpha2 * clamp(outline2.a - c.a - outline1.a, 0, 1), 0, 1);
				outline03.a =c.a- clamp(alpha1 * clamp(outline03.a - c.a, 0, 1), 0, 1);
				outline3.a = clamp(alpha2 * clamp(outline3.a - c.a - outline1.a, 0, 1), 0, 1);

				fixed4 ret = (1 - c.a) * (outline1 + outline2) + c * c.a * i.color * 1 / (_BloomFallOff + 1);
				ret.a = clamp((outline1.a + outline2.a + c.a * i.color.a), 0, 1);

				outline3.a = (1-outline3.a)-(1-ret.a);
				float4 outline3Col = float4(outline3.a,outline3.a,outline3.a,outline3.a);
				//float4 outline3Col02 = float4(outline03.a,outline03.a,outline03.a,outline03.a);
				ret.rgb +=outline3Col.rgb;
				//ret.rgb +=pow(outline3Col02.rgb,2);

				return ret;
			}

			ENDCG
		}
	}

	Fallback "Sprites/Default"
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃斋的和尚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值