【Unity】【UI Shader】关于用Shader实现字体的描边和阴影

前言

描边和阴影,Unity本来是由自带的组件的(Outline和Shadow)。Unity自己的实现方式如下:

Outline:把原文字/图片以往的网格复制4份,然后上下左右各偏移一点距离(相当于多绘制了4遍)。

Shadow:把原文字/图片的网格复制1份,然后往某个方向偏移一点(相当于多绘制了1遍)。

我觉得是挺蛋疼的,所以就突发奇想干脆用Shader来实现会不会好一点。

 

正文:

由于本人水平有限,所以大部分代码都是参考网上的,代码放最后了。

代码里实现的效果如下所示:

其实发现本来想写描边的,结果搞成阴影了。不过问题不大,可以来分析一下:

这个Shader的思路就是写2个Pass,第一个Pass把原输入的网格扩大一点(注意调整扩大后的偏移),然后把他的颜色调整为黑色。然后再写1个Pass正常绘制,叠加在黑色的文字上面。但是这种实现方法有局限性:在设置阴影与原文字差别不大的时候可以 (_OutlineWidth的值大概是 0.01左右),一旦把阴影(或者说描边)的宽度扩大就会出现问题:

可以看到,这个Shader会导致文字的整体放大(而且还有网格漂移的问题),最后没法和原有文本很好地叠加在一起。我觉得是不行的,这种和我预想的描边/阴影效果差别挺大的。如果继续按照这个思路来搞,按实现秒表就再加4个Pass,前后左右各偏移一丢丢就可以了。Pass里面的内容倒是都大同小异。

 

结论:

我这个方法能做个参考吧,但是我觉得这个Shader不行,没有达到我想要的效果。

照这个思路的话,无论是描边还是阴影都只能描一条很细的边。目前我实现的效果更像是阴影,如果要写描边其实也比较容易,最笨的就是再写4个Pass。思路和Unity原有的是一样的,都是上下左右各偏移一点点。但是如果这么搞的话,那描边+阴影+原本的文字绘制就有6个Pass了。你说和原有的Unity方法性能相差几何?我觉得其实优势不大了……

而且这个思路最后做完,其实效果和Unity自带的组件效果是差不多的,或者说没什么大的区别。

我觉得是无用功了~

不过是不是有能用1个Pass就把描边+阴影效果都实现,而且还能解决描边不重合的方法呢?我觉得是有的,不过我目前没找到什么好的思路。

 

代码:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'Shader "UI/UI_ShadowOutline"
{Properties{[PerRendererData] _MainTex("Sprite Texture", 2D) = "white" {}_Color("Tint", Color) = (1,1,1,1)_StencilComp("Stencil Comparison", Float) = 8_Stencil("Stencil ID", Float) = 0_StencilOp("Stencil Operation", Float) = 0_StencilWriteMask("Stencil Write Mask", Float) = 255_StencilReadMask("Stencil Read Mask", Float) = 255_ColorMask("Color Mask", Float) = 15_OutlineWidth("描边宽度",range(0,1)) = 1_Offset("描边偏移",Vector) = (200,0,100,0)[Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip("Use Alpha Clip", Float) = 0}SubShader{Tags{"Queue" = "Transparent""IgnoreProjector" = "True""RenderType" = "Transparent""PreviewType" = "Plane""CanUseSpriteAtlas" = "True"}Stencil{Ref[_Stencil]Comp[_StencilComp]Pass[_StencilOp]ReadMask[_StencilReadMask]WriteMask[_StencilWriteMask]}Cull OffLighting OffZWrite OffZTest[unity_GUIZTestMode]Blend SrcAlpha OneMinusSrcAlphaColorMask[_ColorMask]Pass{Name "Default"CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma target 2.0#include "UnityCG.cginc"#include "UnityUI.cginc"#pragma multi_compile __ UNITY_UI_CLIP_RECT#pragma multi_compile __ UNITY_UI_ALPHACLIPstruct appdata_t{float4 vertex   : POSITION;float4 color    : COLOR;float2 texcoord : TEXCOORD0;UNITY_VERTEX_INPUT_INSTANCE_ID};struct v2f{float4 vertex   : SV_POSITION;fixed4 color : COLOR;float2 texcoord  : TEXCOORD0;float4 worldPosition : TEXCOORD1;UNITY_VERTEX_OUTPUT_STEREO};sampler2D _MainTex;fixed4 _Color;fixed4 _TextureSampleAdd;float4 _ClipRect;float4 _MainTex_ST;float _OutlineWidth;float4 _Offset;v2f vert(appdata_t v){v2f OUT;UNITY_SETUP_INSTANCE_ID(v);UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);OUT.worldPosition = v.vertex;OUT.color = v.color * _Color;OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);//描边;_OutlineWidth += 1;float3 targetPosition = OUT.worldPosition * _OutlineWidth;targetPosition.z = v.vertex.z;targetPosition.x -= (_OutlineWidth - 1) * _Offset.x + _Offset.y;targetPosition.y -= (_OutlineWidth - 1) * _Offset.z + _Offset.w;OUT.vertex = UnityObjectToClipPos(targetPosition);//OUT.vertex.xy *= _OutlineWidth;return OUT;}fixed4 frag(v2f IN) : SV_Target{half4 targetColor = half4(0,0,0,1);half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * targetColor;#ifdef UNITY_UI_CLIP_RECTcolor.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);#endif#ifdef UNITY_UI_ALPHACLIPclip(color.a - 0.001);#endifreturn color;}ENDCG}Pass{Name "Default"CGPROGRAM#pragma vertex vert#pragma fragment frag#pragma target 2.0#include "UnityCG.cginc"#include "UnityUI.cginc"#pragma multi_compile __ UNITY_UI_CLIP_RECT#pragma multi_compile __ UNITY_UI_ALPHACLIPstruct appdata_t{float4 vertex   : POSITION;float4 color    : COLOR;float2 texcoord : TEXCOORD0;UNITY_VERTEX_INPUT_INSTANCE_ID};struct v2f{float4 vertex   : SV_POSITION;fixed4 color : COLOR;float2 texcoord  : TEXCOORD0;float4 worldPosition : TEXCOORD1;UNITY_VERTEX_OUTPUT_STEREO};sampler2D _MainTex;fixed4 _Color;fixed4 _TextureSampleAdd;float4 _ClipRect;float4 _MainTex_ST;float _OutlineWidth;v2f vert(appdata_t v){v2f OUT;UNITY_SETUP_INSTANCE_ID(v);UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);OUT.worldPosition = v.vertex;OUT.color = v.color * _Color;OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);return OUT;}fixed4 frag(v2f IN) : SV_Target{half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;#ifdef UNITY_UI_CLIP_RECTcolor.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);#endif#ifdef UNITY_UI_ALPHACLIPclip(color.a - 0.001);#endifreturn color;}ENDCG}}}

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1621051.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【Android】MyTool 工具界面:手电筒

文章目录 MyTool 工具界面:♦ 回顾♦ 设置 activity_my_tool.xml 界面♦ 编写 MyToolActivity 实现功能界面跳转♦ 创建 activity_flash_light.xml 手电筒界面♦ 编写 FlashLightActivity 实现功能♦ 修改AndroidManifest.xml文件授权♦ 测试 MyTool 工具界面&#…

定时器中断学习和简单应用

定时器中断&简单应用 定时器中断基本介绍清楚明白工作原理定时器结构 主要内容两个寄存器初始化程序 简单应用-秒表基本功能代码详解 彩蛋:对于独立按键的使用没啥硬核内容,就是初学者萌新入门,学长大佬请移步 定时器中断 基本介绍 清…

自学HarmonyOS应用开发(62)- 使用对象关系映射数据库保存设定信息

除了地图数据,秒表应用还有一些其他希望保存的数据,例如上次定位的位置,地图画面的缩放比例等。本文介绍通过对象关系映射数据库技术保存这些信息的方法。 通用的设定信息表 下面的代码定义了用于保存设定信息的通用的表结构: E…

Git企业开发控制理论和实操-从入门到深入(七)|企业级开发模型

前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…

模2运算规则

模2加法 模2加法没有进位,等同于异或运算。一位数的模2加法规则如下: 0 0 0 0 1 1 1 0 1 1 1 0 多位数的模2加法中,每一位都按照上面的规则进行,例如: 当多个数相加,对应位置上如果有偶数个1,…

知识图谱实战应用25-基于py2neo的超市商品的图谱构建与商品推荐系统的实现

大家好,我是微学AI,今天给大家介绍一下知识图谱实战应用25-基于py2neo的超市商品的图谱构建与商品推荐系统的实现,本篇文章,我将指导大家如何使用py2neo和Neo4j构建一个实用的超市商品知识图谱和推荐系统。该系统可以帮助用户快速找到感兴趣的商品,并提供个性化的推荐服务…

pygame实现物体运动拖尾尾迹

文章目录 前言主要内容讲解:代码 总结更多宝藏 前言 😎🥳😎🤠🤖🙈💭🍳🍱 本文我们来讲一下如何使用pygame实现一个拖尾特效。 主要内容 🦞&am…

pe_xscan 增加 O31 项

O31项 对应的项目: 开机、关机脚本 用户登录、注销脚本

LeetCode第1~5题解

CONTENTS LeetCode 1. 两数之和LeetCode 2. 两数相加LeetCode 3. 无重复字符的最长子串 LeetCode 1. 两数之和 【题目描述】 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。…

linux下运行win10效果好不好,Win10不好用?继续坚守Win7的人依然巨多

前不久,微软发布消息称Windows 10操作系统市场占有率终于突破50%。而近日,安全厂商卡巴斯基发布的8月下旬最新研究报告也印证了这一点,并且从数据来看,Windows 10系统的占有率还有小幅度的增长,达到了53%左右。 退休时…

其实win10要比win7的安全性强很多

随着win10系统的一步步更新,用户体验度也越来越好,更多的用户也换了win10的系统,但还是有一部分用户依然雷打不动的信任着win7。下面小编来分析一下win7和win10到底有着怎样的差别,相信看完下文,你也会想升级win10系统…

W7-2495X参数 至强W72495X功耗

W7-2495X采用10纳米工艺二十核心四十线程CPU主频 2.6GHz动态加速频率 4.8GHz 热设计功耗(TDP) 225W支持最大内存容量 2TB内存类型 DDR5 4800MHz W7-2495X性能怎么样这些点很重要 http://www.adiannao.cn/du

电脑装了w10没有w7流畅怎么办?

如果我们对自己的电脑进行了系统的重装,在电脑装了win10系统之后发现没有win7流畅的话,很多小伙伴不知道是什么情况应该怎么解决。 那么据微点阅读小编所知可能是我们电脑硬件设施的不兼容所导致的。我们可以在官网上查看win10系统的配置要求是否符合自…

W7-2475X参数 至强W72475X功耗

W7-2475X采用10纳米制作工艺二十核心四十线程CPU主频 2.6GHz动态加速频率 4.8GHz 热设计功耗(TDP) 225W支持最大内存容量 2TB内存类型 DDR5 4800MHz W7-2475X性能怎么样这些点很重要 http://www.adiannao.cn/du

Intel 至强 W7-3465X参数 W73465X功耗

至强 W7-3465X采用10纳米 制作工艺 二十八核心五十六线程CPU主频 2.5GHz动态加速频率 4.8GHz热设计功耗(TDP) 300W支持最大内存容量 4TB 内存类型 DDR5 4800MHz W7-3465X性能怎么样这些点很重要 http://www.adiannao.cn/du

五类造成Windows 7假死的原因及处理

Windows 7虽好,可是小问题不断。从Beta版本至今,很多朋友遇到最严重的问题就是资源管理器偶尔或者经常失去响应,虽然不是什么非重装的问题,但是时不时电脑卡上一段时间,谁都觉得很烦。那么到底Windows 7在哪些情况下会…

高傲的win7

高傲的win7 首先为win7证明:本文内容和本人下载的系统版本以及硬件细节有关,并不能代表所有的win7种族。 好久没有写博客了,主要是因为把很多东西都记录在笔记里边了,但是感觉写博客和笔记还是不太一样,笔记就是随时…

我对windows7简单评论

10月25日受朋友的邀请参加了弘博软件教育学院成功举办的windows 7发布会 发现不止是我一个对windows 7偏爱有加。这里这里在座师生也是windows7 的粉丝。 windows 7发布会一次又一次的成举办功也源于它独特的性能,带给我们的方便、快捷。 经过我近一个月的使用&…

09年IT界最愚蠢的九件事 Windows7精简版UAC上榜(转)

据国外媒体报道,临近岁末,资讯网站eWeek于上周评出了《九款年度重磅产品》。无独有偶,该网站此番又评选出2009年度最不受用户欢迎的九大事件: 1、亚马逊删书门 今年七月份,在线销售巨人亚马逊(Amazon&…

历经十年,还有一个月,Windows 7 生命周期将结束,相信很多人还是觉得win7不错的

距离 Microsoft 终止对 Windows 7 的支持只剩一个月的时间了,到 2020 年 1 月 14 日,这款经典的操作系统就要和大家 say goodbye 了。 2009 年 7 月 4 日,Windows 7 正式开发完成,到现在已经整整 10 岁。它在 Vista 前辈的基础上发展而来,界面友好,功能强大,使用高效,因…