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

news2024/9/20 22:30:51

文章目录

  • 前言
  • Shader
    • 1. 内描边
    • 2. 外描边
  • Shader Graph
    • 1. 2d图片描边
    • 2. 带炫光的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

参考

  • 【视频】https://www.youtube.com/watch?v=Eyx3EfqqfMw&list=PLzDRvYVwl53tqzN5R-j33Sd7kf_f6b6z4
  • 【文章】https://www.jianshu.com/p/c68a730e9a8b

完结

如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦

好了,我是向宇,https://xiangyu.blog.csdn.net/

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你有任何问题,欢迎你来评论私信告诉我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

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

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

相关文章

2023最新整理的 Elasticsearch 21道面试题

1、为什么要使用 Elasticsearch? 系统中的数据&#xff0c; 随着业务的发展&#xff0c; 时间的推移&#xff0c; 将会非常多&#xff0c;而业务中往往采用模糊查询进行数据的 搜索&#xff0c;而模糊查询会导致查询引擎放弃索引&#xff0c; 导致系统查询数据时都是全表扫描&…

Unity3D 场景添加obj模型

有一个立方体的obj模型&#xff1b;将其拖到Assets文件夹节点上&#xff0c;在此节点放手&#xff0c;资源被加入项目&#xff1b; 在右侧显示出对象概览&#xff1b; 点击箭头&#xff0c;显示此模型下的子对象&#xff1b; 然后按住Assets面板中的cube1对象&#xff0c;拖动…

3分钟阿里云轻量应用服务器和云服务器的区别对比

阿里云服务器ECS和轻量应用服务器有什么区别&#xff1f;云服务器ECS是明星级云服务器&#xff0c;轻量应用服务器可以理解为简化版的云服务器ECS&#xff0c;轻量适用于单机应用&#xff0c;云服务器ECS适用于集群类高可用高容灾应用&#xff0c;阿里云百科来详细说下阿里云轻…

科研论文中SCI,SSCI ,CSSCI是什么

目录 1 SCI 2 SSCI 3 CSSCI 什么是SCI&#xff0c;SSCI &#xff0c;CSSCI 目前&#xff0c;在国际科学界&#xff0c;如何正确评价基础科学研究成果已引起越来越广泛的关注。而被SCI、SSCI收录的科技论文的多寡则被看作衡量一个国家的基础科学研究水平、科技实力和科技论文水平…

以太网之IP协议(七)

目录 一、IP协议的功能 1.1 IP地址 1.2 IP路由 1.2.1 路由原理 1.2.2 路由控制表 1.3 IP分包与组包 二、IP地址 2.1 IP地址分类 2.2 多播地址 2.2.1 广播地址 2.2.2 组播地址 2.3 子网掩码 三、IP帧格式 一、IP协议的功能 数据链路层提供直连两个设备之间的通信功…

【Linux系统编程】Linux编辑器——vim

文章目录 1. 什么是vim2. vim的常用模式3. vim的基本操作4. vim命令集4.1 命令模式命令集复制粘贴依次撤销上一次操作对撤销进行撤销&#xff08;恢复&#xff09;剪切&删除移动光标&#xff08;上下&#xff09;移动光标&#xff08;左右&#xff09;文本内容大小写切换替…

javaTCP数据报套接字编程

TCP套接字编程 1.ServerSocket API1.1ServerSocket 的构造方法1.2ServerSocket 方法&#xff1a; 2.Socket API2.1Socket构造方法2.2Socket方法 3.TCP回显服务器4.TCP中的长短连接5.C10M问题 TCP提供的API主要有两个类&#xff1a;一个是专门给服务器用的SeverSocket对象&#…

MyBatis-Plus框架

说明&#xff1a;Mybaits-Plus是Mybatis框架的升级&#xff0c;该框架提供了一系列API&#xff0c;用于操作数据&#xff0c;可以免受手搓SQL语句的痛苦。 一、使用 第一步&#xff1a;添加依赖 使用前&#xff0c;需先添加对应的依赖&#xff0c;建议使用最新的版本 <d…

有什么事让你觉得在Linux上顺理成章,换到Windows上就令你费解?

&#x1f388;个人主页:&#x1f388; :✨✨✨初阶牛✨✨✨ &#x1f43b;推荐专栏1: &#x1f354;&#x1f35f;&#x1f32f;C语言初阶 &#x1f43b;推荐专栏2: &#x1f354;&#x1f35f;&#x1f32f;C语言进阶 &#x1f511;个人信条: &#x1f335;知行合一 &#x1f…

Linux红帽认证适合哪些人学习

近几年来&#xff0c;技术的迭代速度越来越快&#xff0c;云计算&#xff0c;大数据&#xff0c;人工智能&#xff0c;物联网等技术扑面而来&#xff0c;全球各大互联网公司都在抢先发展这些技术&#xff0c;而无一例外的这些技术背后都是使用的Linux系统&#xff0c;双11&…

JAVA_SSM Demo(WEB端)

仓库地址&#xff1a;https://gitee.com/ThMyGitee/SSMDemo.git CSDN的友友们&#xff0c;项目如果适合您的话&#xff0c;麻烦给个小小的Star&#xff0c;谢谢啦&#xff01; JAVA_SSM Demo(WEB端) 1.开发环境 JDK1.8 Tomcat 8.5.60 IDEA 2019.3 MySQL 5.7.20 Maven 3.6 S…

USB协议总结

1、简介 在了解USB协议之前&#xff0c;先了解下该总线协议出现的背景。在USB总线出现之前&#xff0c;计算机与键盘、鼠标、扫描仪、打印机都使用专用的接口连接&#xff0c;不同设备的接口不能互用&#xff0c;扩展性很差。每次插拔设备都要关闭计算机&#xff0c;不支持热插…

【Matlab】智能优化算法_麻雀搜索算法SSA

【Matlab】智能优化算法_麻雀搜索算法SSA 1.背景介绍2.数学模型3.文件结构4.伪代码5.详细代码及注释5.1 Get_Functions_details.m5.2 main.m5.3 SSA.m 6.运行结果7.参考文献 1.背景介绍 麻雀通常是群居的鸟类&#xff0c;有很多种类。它们分布在世界的大部分地区&#xff0c;喜…

TI毫米波雷达软硬件概述

TI毫米波雷达概述 1.TI毫米波雷达传感器芯片及分类&#xff1a;1.1 工业毫米波雷达传感器器件选型应用场景 1.2 汽车毫米波雷达选型使用场景 1.3 基于AWR2243 的 TI 级联雷达 &#xff1a;1.4 不喜欢看文字的也可以戳视频-> 2. TI软件入门概述&#xff1a;2.1 TI RadarToolb…

【C】指针详解(一篇文章带你玩转指针)

指针详解 指针是什么&#xff1f;指针和指针类型指针加减整数指针的解引用 野指针野指针的成因如何规避野指针 指针和数组的关系数组名是什么&#xff1f; 二级指针二级指针是什么&#xff1f;二级指针的运算 字符指针指针数组和数组指针指针数组数组名和&数组名数组指针数…

开源一款轻量线程池项目

基于Arrow的轻量线程池 大家好&#xff0c;我是光城&#xff0c;最近花了几周业余时间&#xff0c;开发出这款轻量线程池&#xff0c;代码也全部开源啦&#xff0c;欢迎大家star。 本线程池的设计与实现会有涉及非常多的知识&#xff0c;这些内容也都会以视频的方式分享在知识星…

分析气象数据:向Python Cartopy地图中添加循环点

大家好&#xff0c;在使用Python和Cartopy对气候数据进行可视化分析的过程中&#xff0c;有一个叫做循环点&#xff08;cyclic point&#xff09;的术语&#xff0c;它在地理空间栅格数据可视化领域中很重要。 1.循环点的定义和作用 有时&#xff0c;当我们试图绘制地理空间数…

性能测试的基本概念和重要指标

这里写自定义目录标题 一、什么是性能测试二、为什么要学习性能三、性能测试与功能测试的区别1、性能测试和功能测试的区别&#xff1f;2、性能测试是在什么时候做?3、我们在做我们的产品的时候&#xff0c;我们只做功能不做性能可不可以&#xff1f;4、性能测试主要是这几个方…

金融计量学第2课堂-金融时间序列线性模型

量化策略开发&#xff0c;高质量社群&#xff0c;交易思路分享等相关内容 一、相关性和平稳性 1、相关性 &#xff08;1&#xff09;皮尔森相关系数 皮尔森相关系数是最常见、最常用的一个相关系数计算方法。作为衡量两个随机变量x和y线性相关程度的重要指标&#xff0c;在这…

赋能智能智造-RK3568智能主板助力机器人产业高速发展

机器人作为现代制造业的重要一环&#xff0c;正在以惊人的速度推动着生产效率和智能化水平的提升&#xff0c;它们在生产线上的准确操作和高效工作&#xff0c;为企业带来了巨大的竞争优势。关于工业机器人的编程和控制技术&#xff0c;在过去几年中已经有了很多发展和新的应用…