推广

Unity Shader 极简实践5——2D图片描边

iseeyu2年前 (2024-02-21)推广144

《赛博朋克》朱迪·阿尔瓦雷兹

这篇文章描述如何对2D图片(Unity 中的 Sprite 和 UGUI Image) 做描边

1. 内描边

思路:在片元着色器中,判断当前片元的上下左右像素(使用数值width来确定上下左右“多远”,从而得到描边的宽度),上下左右四个像素的 alpha 分量相乘越接近0,则该像素颜色越接近描边颜色。大致可以理解为如果某像素p的上下左右其中某个像素为透明像素,则p处于边缘,将p像素绘制为描边颜色。
代码如下:

Shader "Custom_Shader/ImageInnerOutline"
{
    Properties
    {
        _MainTex ("Sprite Texture", 2D) = "white" {}
        _OutlineWidth ("Outline Width", float) = 1
        _OutlineColor ("Outline Color", Color) = (1,1,1,1)
    }
    SubShader
    {
        Blend SrcAlpha OneMinusSrcAlpha
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            sampler2D _MainTex;
            float4 _MainTex_ST;
            half4 _MainTex_TexelSize;
            float _OutlineWidth;
            float4 _OutlineColor;

            struct appdata
            {
                float4 vertex   : POSITION;
                float2 uv : TEXCOORD0;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                half2 uv  : TEXCOORD0;
                half2 left : TEXCOORD1;
                half2 right : TEXCOORD2;
                half2 up : TEXCOORD3;
                half2 down : TEXCOORD5;
            };

            v2f vert(appdata i)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(i.vertex);
                o.uv = TRANSFORM_TEX(i.uv, _MainTex);
                o.left = o.uv + half2(-1, 0) * _MainTex_TexelSize.xy * _OutlineWidth;
                o.right = o.uv + half2(1, 0) * _MainTex_TexelSize.xy * _OutlineWidth;
                o.up = o.uv + half2(0, 1) * _MainTex_TexelSize.xy * _OutlineWidth;
                o.down = o.uv + half2(0, -1) * _MainTex_TexelSize.xy * _OutlineWidth;
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                fixed4 c = tex2D(_MainTex, i.uv);
                float transparent = tex2D(_MainTex, i.left).a * tex2D(_MainTex, i.right).a * tex2D(_MainTex, i.up).a * tex2D(_MainTex, i.down).a;
                c.rgb = lerp(_OutlineColor.rgb, c.rgb, transparent);
                
                return c;
            }
            ENDCG
        }
    }
}

描边效果:

内描边效果

内描边会占用图片本身边缘的非透明像素,当描边宽度增大时当效果为

描边宽度较大

2. 外描边

思路:在片元着色器中,处理像素p,针对p的上下左右四个像素采样(使用一个变量width来控制描边宽度,也就是处理上下左右多远的像素),若p本身是透明像素,则

  • 若上下左右存在非透明像素,则当前像素p返回描边颜色
  • 若上下左右都是透明像素,则返回透明即可

若 p 本身非透明像素,则返回本身颜色即可
代码如下:

Shader "Custom_Shader/ImageOuterOutline"
{
    Properties
    {
        _MainTex ("Sprite Texture", 2D) = "white" {}
        _OutlineWidth ("Outline Width", float) = 1
        _OutlineColor ("Outline Color", Color) = (1.0, 1.0, 1.0, 1.0)
        _AlphaValue ("Alpha Value", Range(0, 1)) = 0.1
    }
    SubShader
    {
        Blend SrcAlpha OneMinusSrcAlpha

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

            sampler2D _MainTex;
            float4 _MainTex_ST;
            half4 _MainTex_TexelSize;
            float _OutlineWidth;
            float4 _OutlineColor;
            float _AlphaValue;

            struct appdata
            {
                float4 vertex   : POSITION;
                float2 uv : TEXCOORD0;
                float4 normal : NORMAL;
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                half2 uv  : TEXCOORD0;
                half2 left : TEXCOORD1;
                half2 right : TEXCOORD2;
                half2 up : TEXCOORD3;
                half2 down : TEXCOORD5;
            };

            v2f vert(appdata i)
            {
                v2f o;
                o.vertex = o.vertex + i.normal * _OutlineWidth;
                o.vertex = UnityObjectToClipPos(i.vertex);
                o.uv = TRANSFORM_TEX(i.uv, _MainTex);
                o.left = o.uv + half2(-1, 0) * _MainTex_TexelSize.xy * _OutlineWidth;
                o.right = o.uv + half2(1, 0) * _MainTex_TexelSize.xy * _OutlineWidth;
                o.up = o.uv + half2(0, 1) * _MainTex_TexelSize.xy * _OutlineWidth;
                o.down = o.uv + half2(0, -1) * _MainTex_TexelSize.xy * _OutlineWidth;
                return o;
            }

            fixed4 frag(v2f i) : SV_Target
            {
                float transparent = tex2D(_MainTex, i.left).a + tex2D(_MainTex, i.right).a + tex2D(_MainTex, i.up).a + tex2D(_MainTex, i.down).a;
                fixed4 col = tex2D(_MainTex, i.uv);

                if (col.a < 0.1) {
                    return step(_AlphaValue, transparent) * _OutlineColor;
                } else {
                    return col;
                }
            }
            ENDCG
        }
    }
}

外描边效果:

外描边效果

外描边不会占用图片非透明像素,但要求图片外围要有足够但透明像素,当调整外描边宽度时,效果:

描边宽度较大

  • 描边宽度较大时,Image 图片顶部和左边有平滑的切割是图片本身的范围

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/56949.html

相关文章

代运营公司网络推广(宝安短视频营销推广公司哪家专业)

代运营公司网络推广(宝安短视频营销推广公司哪家专业)

如今,互联网的飞速发展已经是众所周知了,很多的公司都选择通过互联网来提升自己的知名度、美誉度,这是一个非常好的选择,但是很多公司并不知道应该怎么做才能让自己的企业信息变得更加的有价值。如果自己的信息无法做到很好的把控,那么很多的企业就会选择代运营公司来为自己做推广来提升自己的信息影响力。当...

手机网站推广排名优化有哪些技巧。

手机网站推广排名优化有哪些技巧。

随着人们对智能手机的依赖性越来越强,很多重视移动端seo优化的企业迅速崛起,其实移动站和PC站seo优化同等重要,只是要根据用户的不同需求,对移动站点做各种SEO优化调整,达到的预期效果差不多。那么移动端网站SEO优化需要哪些技巧? 其中百度官方意见重要的两点:一是使用合理的div和css架构,建...

如何避免网站K的危险。

如何避免网站K的危险。

一、过错的关键词挑选 仅针对首要关键词排名进行优化,不充分考虑长尾词优化。用户目的不强,很难构成有用的转化。 二、关键词布局过错 许多SEO以为在文章中添加您想要的关键词能够进步您在查找引擎中的排名,但在大多数情况下,它被判定为垃圾邮件,关键词密度很高。 SEO作用不会后退。面临关...

金牌卖家在卖家中心哪里(淘宝金牌卖家申请条件)

金牌卖家在卖家中心哪里(淘宝金牌卖家申请条件)

  淘宝金牌卖家该怎么申请?   对于很多在淘宝上面开过店铺的买家们来说,可能也都会听说过淘宝金牌卖家这样的一个名词,那么到底什么是淘宝金牌卖家?淘宝金牌卖家又该如何来进行申请呢?下面就让我们一起来了解一下吧。      其实所谓的淘宝金牌卖家也是淘宝网站上面对于卖家们的一种评价,就相当于...

今日头条、爱奇艺等广告样式及计费模式汇总!

今日头条、爱奇艺等广告样式及计费模式汇总!

  信息流广告样式: 1.大图:一个标题+大图 2.单图:一个标题+1个小图 3.组图:一个标题+3个小图 视频贴片:APP短视频播放完以后出现的广告 暂停贴片:视频播放点击暂停键出现的广告 动态广告:视频播放前的广告,视频贴片广告...

淘宝代理店铺怎么做(代理网店怎么做)

淘宝代理店铺怎么做(代理网店怎么做)

首先要寻找货源,确定好自己店铺的产品,再申请做代理,商家去代理商那里选品,将产品上传到店铺之后,有人下单,就去代理商那里下单,发货后做好物流查询。...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片