【实现100个unity特效之2】使用shader和shader Graph实现2d图片描边效果(附源码)

简介: 【实现100个unity特效之2】使用shader和shader Graph实现2d图片描边效果(附源码)

前言

最近在学习shader Graph相关内容,其实关于实现2d图片描边效果,网上可以看到很多教程,但是我发现大多数都是基于比较老旧的2018unity版本,可是我们实际开发使用可能是比较新的2021及以上版本,差别还是有的,实际在升级或者使用过程中,会遇到诸多问题,而且也很少有人会分享shader Graph的连线图源码

没有的话我就想着把我的学习笔记和源码整理分享出来吧,于是就有了这篇文章

Shader

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 图片顶部和左边有平滑的切割是图片本身的范围

Shader Graph

1. 2d图片描边

(ps:图片看不清也没关系,文件末尾我会放手demo源码,不清楚的可以直接查看源码进行学习)

不同图片上的效果

2. 带炫光的2d图片描边

不同图片上的效果

最终演示效果

源码

https://gitcode.net/unity1/unity2d-shader-picturestroke

参考

目录
相关文章
|
4天前
|
图形学
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)(上)
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)
10 2
|
4天前
|
图形学
【推荐100个unity插件之19】武器拖尾特效插件——Pocket RPG Weapon Trails(2d 3d通用)
【推荐100个unity插件之19】武器拖尾特效插件——Pocket RPG Weapon Trails(2d 3d通用)
7 0
|
4天前
|
图形学
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)(下)
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)(下)
8 0
|
4天前
|
存储 JSON 关系型数据库
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版13(完结,附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版13(完结,附带项目源码)
11 0
|
4天前
|
图形学
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版12(附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版12(附带项目源码)
11 0
|
4天前
|
存储 图形学
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版11(附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版11(附带项目源码)
10 0
|
4天前
|
图形学
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版10(附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版10(附带项目源码)
8 0
|
4天前
|
图形学 容器
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版9(附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版9(附带项目源码)
9 0
|
4天前
|
图形学
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版3(附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版3(附带项目源码)
16 2
|
4天前
|
图形学
【制作100个unity游戏之28】花半天时间用unity复刻童年4399经典小游戏《黄金矿工》(附带项目源码)
【制作100个unity游戏之28】花半天时间用unity复刻童年4399经典小游戏《黄金矿工》(附带项目源码)
15 0