unity ugui自定义Text字体描边优化性能

在unity的ugui的用于Text描边的组件outline中,其中的实现是将字体copy出几份往外放置形成背景黑边,随之带来的是性能的高消耗。如果是一两个Text描边还好,如果同屏有大量Text在使用其在描边时,其性能消耗提高十分明显,甚至直接影响到了游戏FPS。
因此,同屏Text描边多时有必要优化一下,因此写一个可以实现Text描边的shader。
一样的道理,shader中有2个Pass,但多个Text在使用其描边时,Unity会自动进行批处理,所以整体上只会多出一个drawcall,相比ugui内置的outline组件,此shader性能提升巨大,效果明显!

用法: 1,导入此TextOutline.shader,

2,Project视窗下右键Create->Material,命名为TextOutline,然后它选中在 Inspector视窗中最上端Shader属性选择Custom->TextOutline。

3,将2步骤的TextOutline Material赋给需要描边的ugui Text控件即可。

效果:

在这里插入图片描述

代码:

TextOutline.shader :


Shader "Custom/TextOutline" {
	Properties{
		_MainTex("Font Texture", 2D) = "white" {}
		_Color("Text Color", Color) = (1,1,1,1)
		_OutlineColor("Outline Color", Color) = (0,0,0,1)
		_StencilComp("Stencil Comparison", Float) = 3.000000
		 _Stencil("Stencil ID", Float) = 1.000000
		 _StencilOp("Stencil Operation", Float) = 0.000000
		 _StencilWriteMask("Stencil Write Mask", Float) = 0.000000
		 _StencilReadMask("Stencil Read Mask", Float) = 1.000000
	}

		SubShader{

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

			Lighting Off Cull Off ZTest Always ZWrite Off
			Blend SrcAlpha OneMinusSrcAlpha
			Stencil {
				Ref[_Stencil]
				ReadMask[_StencilReadMask]
				WriteMask[_StencilWriteMask]
				Comp[_StencilComp]
				Pass[_StencilOp]
			}
			//ColorMask[_ColorMask]

			//第一个Pass,实现Text内容背景颜色,并向外扩大_OutlineWidth
			Pass {
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON
				#include "UnityCG.cginc"

				struct appdata_t {
					float4 vertex : POSITION;
					fixed4 color : COLOR;
					float2 texcoord : TEXCOORD0;
					//UNITY_VERTEX_INPUT_INSTANCE_ID
				};

				struct v2f {
					float4 vertex : SV_POSITION;
					fixed4 color : COLOR;
					float2 texcoord : TEXCOORD0;
					UNITY_VERTEX_OUTPUT_STEREO
				};

				sampler2D _MainTex;
				uniform float4 _MainTex_ST;
				uniform float4 _MainTex_TexelSize;
				uniform fixed4 _Color;
				uniform fixed4 _OutlineColor;


				v2f vert(appdata_t v)
				{
					v2f o;
					UNITY_SETUP_INSTANCE_ID(v);
					UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
					o.vertex = UnityObjectToClipPos(v.vertex);
					o.color = v.color * _Color;
					o.texcoord = TRANSFORM_TEX(v.texcoord,_MainTex);
					return o;
				}
				//确定每个像素周围8个像素的坐标。
				static const float2 dirList[9] = {
					float2(-1,-1),float2(0,-1),float2(1,-1),
					float2(-1,0),float2(0,0),float2(1,0),
					float2(-1,1),float2(0,1),float2(1,1)
				};
				//谋取dirList第dirIndex个方位的透明度值。
				float getDirPosAlpha(float index, float2 xy) {
					float2 curPos = xy;
					float2 dir = dirList[index];
					float2 dirPos = curPos + dir * _MainTex_TexelSize.xy * 0.6;
					return tex2D(_MainTex, dirPos).a;
				};
				//对于每个像素,传入片元参数v2f i ,获取次像素周围和自身的共9个像素进行透明度叠加。
				//那么得出的结果就是非透明的区域被放大了,形成了黑边。
				float getShadowAlpha(float2 xy) {
					float a = 0;
					float index = 0;
					a += getDirPosAlpha(index, xy);
					a += getDirPosAlpha(index++, xy);
					a += getDirPosAlpha(index++, xy);
					a += getDirPosAlpha(index++, xy);
					a += getDirPosAlpha(index++, xy);
					a += getDirPosAlpha(index++, xy);
					a += getDirPosAlpha(index++, xy);
					a += getDirPosAlpha(index++, xy);
					a += getDirPosAlpha(index++, xy);
					a = clamp(a,0,1);
					return a;
				}


				//由于渲染Text内容时,Text字上没有被渲染的区域是透明的,也就是透明度a值是0,
				//所以只要将有内容的区域往外透明度为0的区域扩展一些像素将就能够形成描边效果。
				fixed4 frag(v2f i) : SV_Target
				{
					fixed4 col = _OutlineColor;
					float2 xy = i.texcoord.xy;
					col.a *= getShadowAlpha(xy);
					return col;
				}
				ENDCG
			}
			//第二个Pass,常规渲染Text内容。

			Pass {
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma multi_compile _ UNITY_SINGLE_PASS_STEREO STEREO_INSTANCING_ON STEREO_MULTIVIEW_ON
				#include "UnityCG.cginc"

				struct appdata_t {
					float4 vertex : POSITION;
					fixed4 color : COLOR;
					float4 texcoord : TEXCOORD0;
					//UNITY_VERTEX_INPUT_INSTANCE_ID
				};

				struct v2f {
					float4 vertex : SV_POSITION;
					fixed4 color : COLOR;
					float2 texcoord : TEXCOORD0;
					UNITY_VERTEX_OUTPUT_STEREO
				};

				sampler2D _MainTex;
				uniform float4 _MainTex_ST;
				uniform float4 _MainTex_TexelSize;
				uniform fixed4 _Color;

				v2f vert(appdata_t v)
				{
					v2f o;
					UNITY_SETUP_INSTANCE_ID(v);
					UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
					o.vertex = UnityObjectToClipPos(v.vertex);
					o.color = v.color * _Color;
					step(v.texcoord, v.vertex.xy);
					o.texcoord = TRANSFORM_TEX(v.texcoord.xy,_MainTex);
					return o;
				}
				fixed4 frag(v2f i) : SV_Target
				{
					fixed4 col = i.color;
					col.a = tex2D(_MainTex, i.texcoord).a;
					return col;
				}
				ENDCG
			}
		}
}



  • 10
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值