【UnityShader】图片圆角

news2024/12/26 0:59:03

1.需求

        我们在开发的时候,有时候一些按钮或者菜单栏的边角是直角的需要改成圆角,但是让美术重新绘制耽误时间不说也确实没必要,这个时候我们不妨使用一个简单的shader去解决这个问题,下面我们就讲讲这个shader要如何实现。

需求1:可以将图片四角任意一角从直角变为圆角,可控制圆角大小

需求2:在需求一的基础上可以选择是否给图片加上边框,颜色可变

附加小需求:可更改图片透明度

2.实现

2.1. 准备

        在实现之前,除此了解shader的同学可以去了解一下unity内置的一些shader变量和函数,熟悉了这些变量和函数的含义,对我们实现一个shader有很大的帮助。

【UnityShader预备知识】内置变量和函数

2.1.1.Tags

我们先了解一些需要使用的Tags:

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

这些是Unity Shader标签,用于指定渲染顺序、忽略投影、渲染类型以及预览方式。其中,“Transparent”表示该Shader将被渲染在所有不透明物体之后,因此适合用作UI元素或半透明物体的材质。如果你想让这个Shader按照标准的渲染顺序进行渲染,可以去掉“Transparent”标签并将“Queue”改为“Geometry”。

另外,“CanUseSpriteAtlas”允许该Shader使用精灵图集,这对于使用多个精灵制作复杂的图形很有用。如果你想让Shader支持精灵图集,请确保你的项目中已经启用了相应的功能。

2.1.2.Stencil

接下来我们再看一下模板缓冲区Stencil Buffer如何设置:

Stencil
        {
            Ref[_Stencil]
            Comp[_StencilComp]
            Pass[_StencilOp]
            ReadMask[_StencilReadMask]
            WriteMask[_StencilWriteMask]
        }
  • Stencil Buffer(模板缓冲区)是一个与颜色缓冲区和深度缓冲区类似的额外缓冲区,可用于记录每个像素是否被绘制过。当启用模板测试时,只有满足特定条件的像素才会被绘制。
  • Ref[_Stencil]指定了模板缓冲区的参考值,即只有当模板值等于该值时才绘制。
  • Comp[_StencilComp]指定了模板比较函数,例如等于、不等于、小于等等。
  • Pass[_StencilOp]指定了当模板测试失败时的操作,例如替换为Ref[_Stencil]或其他值。
  • ReadMask[_StencilReadMask]和WriteMask[_StencilWriteMask]分别指定了读取和写入模板缓冲区的掩码。

2.1.3.基础设置

shader中需要对光照、深度等进行一些设置,比如:

        Cull Off  //关闭了背面剔除,使得物体的正面和背面都可以被渲染。
        Lighting Off  //关闭了光照计算,这意味着不会对物体表面产生光照影响。
        ZWrite Off  //关闭了深度写入,使得物体不会影响场景的深度信息。
        ZTest[unity_GUIZTestMode]  //指定了深度测试模式,对于GUI元素通常使用Less或Greater模式。
        Blend SrcAlpha OneMinusSrcAlpha  //启用了混合模式,用于控制透明度。
        ColorMask[_ColorMask]  //控制哪些颜色通道会被写入,通常用于控制透明度。

这些设置关闭了背面剔除、光照计算、深度写入,并开启了混合模式,同时还设置了颜色掩码。这通常是用于渲染UI元素的标准设置。其中,Cull Off表示不剔除任何面,Lighting Off表示不进行光照计算,ZWrite Off表示不写入深度缓冲区,ZTest[unity_GUIZTestMode]表示使用Unity GUI的特殊深度测试模式,Blend SrcAlpha OneMinusSrcAlpha表示开启混合模式,使得透明度能够正确显示,ColorMask[_ColorMask]则控制哪些颜色通道会被写入。如果你希望对这些设置进行自定义,可以在Shader中添加相应的标签。

2.2.功能实现思路

2.2.1.直角变圆角

如果要将一个直角变成圆角,那么首先我们得要确定这个圆角的中心点O和半径r,然后将图片超出半径范围的像素进行剔除舍弃即使其alpha=0。以左下角为例:

//左下角
if (x < r && y < r)//x和y分别是当前像素的UV坐标
 {
      anc_size = (x - r) * (x - r) + (y - r) * (y - r);
      if (anc_size > r * r)
       {
           color.a = 0;
        }
  }

首先,我们检查当前像素是否在圆角范围内,如果是,则计算其离中心点的距离(anc_size)。

如果anc_size大于半径的平方(r*r),则说明该像素超出了圆角范围,应被舍弃。其他几个角依次类推,大家可以自己手动画一张图这样更明了一些。需要注意的是UV坐标系,左下角为(0,0),右上角为(1,1)。相信图应该都能画出来,这边我也会在下面贴出来草图以供参考。

其他三角:

//左上角
                if (x < r && y > (height - r))
                {
                    anc_size = (x - r) * (x - r) + (y - (height - r)) * (y - (height - r));
                    if (anc_size > r * r)
                    {
                        color.a = 0;
                    }
                    else if (edge_width > 0 && anc_size > (r - edge_width) * (r - edge_width))
                    {
                        color = edge_color;
                    }
                }
                r = _EdgeCore.z;
                //右下角
                if (x > (width - r) && y < r)
                {
                    anc_size = (x - (width - r)) * (x - (width - r)) + (y - r) * (y - r);
                    if (anc_size > r * r)
                    {
                        color.a = 0;
                    }
                    else if (edge_width > 0 && anc_size > (r - edge_width) * (r - edge_width))
                    {
                        color = edge_color;
                    }
                }
                r = _EdgeCore.y;
                //右上角
                if (x > (width - r) && y > (height - r))
                {
                    anc_size = (x - (width - r)) * (x - (width - r)) + (y - (height - r)) * (y - (height - r));
                    if (anc_size > r * r)
                    {
                        color.a = 0;
                    }
                    else if (edge_width > 0 && anc_size > (r - edge_width) * (r - edge_width))
                    {
                        color = edge_color;
                    }
                }

2.2.2.添加边框

添加边框是什么意思,简单点说就是把图片边上一部分的颜色进行转换,有了上面进行圆角的转换,我们只要根据边框的宽度算出对应的区域范围,将此区域范围内的颜色进行更改即可,依旧以左下角为例:

 if (x < r && y < r)
{
     arc_size = (x - r) * (x - r) + (y - r) * (y - r);
    if (arc_size > r * r)
        {
            color.a = 0;
        }
    else if (b_width > 0 && arc_size > (r - b_width) * (r - b_width))
         {
            color = b_color;
         }
}

在上面我们已经计算出了arc_size,如果它介于半径和半径减去边框宽度之间(即边框区域),则应用边框颜色。这里的r代表圆角半径,x和y分别是当前像素的UV坐标。你可以根据需要修改r和b_width这两个变量来改变圆角大小和边框宽度。同时,你也需要在Shader的Properties块中声明对应的属性。

做到这里,你可能会发现你的效果是这样的:

哎,没错,这个效果说不定也有人有需要也是一个有意思的形状,当然,这还不是完整的边框,刚刚我们只考虑了边角,没有考虑其他地方,所以我们还要对其他地方的边框进行处理:

if (b_width > 0)
{
                    //下边
if (x > _RCorner.w && x < (width - _RCorner.z) && y < b_width)
                    {
                        color = border_color;
                    }
                    //上边
if (x > _RCorner.x && x < (width - _RCorner.y) && (height - y) < b_width)
                    {
                        color = border_color;
                    }
//左边
if (y > _RCorner.w && y < (height - _RCorner.x) && x < b_width)
                    {
                        color = border_color;
                    }
//右边
 if (y > _RCorner.z && y < (height - _RCorner.y) && x > (width - b_width))
                    {
                        color = border_color;
                    }
                }

2.2.3.修改图片透明度

修改透明度的方式很简单,就是对颜色的alpha进行修改:

if (_MainTex_TexelSize.z > 0)
   {
    color = (tex2D(_MainTex, IN.texcoord)) * IN.color;
   }
color.a= _Alpha;

需要注意的是alpha通道要在最后进行设置,以免后面再对颜色进行修改影响其值。

比如你只想改改边框的透明度,你就可以把这段修改放在修改边框那边。

2.3.最终效果

3.下载链接

https://download.csdn.net/download/qq_35064654/89194087

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

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

相关文章

设计模式之观察者模式(优先使用对象组合的原则)的C++实现

观察者模式又称订阅者发布者模式&#xff0c;本篇介绍主要是利用对象组合大于类继承的设计模式原则实现订阅发布模式&#xff0c;这种设计的优点是想订阅数据的类不需要继承订阅者类的抽象类&#xff0c;减少了一层类的继承&#xff1b;当然&#xff0c;具体情况需要可根据需求…

在ios设备上运行Unity Profiler

久违了朋友们。 最近基于Unity 2021.3 和AR Foundation开发了个应用&#xff0c;需要在ipad上实际运行时查看程序的各项指标功耗。 于是乎&#xff0c;我尝试跟随者官方教程来实时调试&#xff0c;现在附上一些心得。 按照官方的三步走&#xff0c;Build and Run理论上会自动…

42岁TVB男艺人曾靠刘德华贴钱出道,苦熬10年终上位

张颕康在无线&#xff08;TVB&#xff09;电视打滚多年&#xff0c;近年在《逆天奇案》第一、二辑凭扎实演技为人留下印象。他还是圈中出名的「爱妻号」&#xff0c;日前在访问期间&#xff0c;张颕康三句不离多谢太太。 较年长的观众或会记得&#xff0c;张颕康初出道以「刘德…

边缘计算智能分析网关V4地面垃圾AI检测算法介绍及场景应用

在传统的卫生监管场景中&#xff0c;无法及时发现地面遗留的垃圾&#xff0c;通过人工巡逻的方式需要大量的人力、物力和时间&#xff0c;而且效率不高&#xff0c;并存在一定的滞后性&#xff0c;而采用地面垃圾AI检测算法则可以大大提高监管效率。 TSINGSEE青犀AI智能分析网…

骑砍2霸主MOD开发(6)-使用C#-Harmony修改本体游戏逻辑

一.C#-Harmony反射及动态注入 利用C#运行时环境的反射原理,实现对已加载DLL,未加载DLL中代码替换和前置后置插桩. C#依赖库下载地址:霸王•吕布 / CSharpHarmonyLib GitCodehttps://gitcode.net/qq_35829452/csharpharmonylib 根据实际运行.Net环境选择对应版本的0Harmony.dll…

【编译原理】03语法分析

1&#xff0c;语法分析的若干问题 1.1 语法分析器的作用 编译器前端的重要组成部分&#xff1a; (1) 根据词法分析器提供的记号流&#xff0c;为语法正确的输入构造分析树(或语法树)。 (2) 检查输入中的语法(可能包括词法)错误&#xff0c;并调用出错处理器进…

MyBatis 核心配置讲解(上)

大家好&#xff0c;我是王有志&#xff0c;一个分享硬核 Java 技术的互金摸鱼侠。 前两篇的文章中我们分别介绍了 MyBatis 和 MyBaits 的应用组成&#xff0c;到这里基础篇的内容就结束了。 从今天开始&#xff0c;我们正式进入 MyBatis 学习的第二阶段&#xff1a;MyBatis 的…

插值与重采样在AI去衣技术中的关键作用

在人工智能&#xff08;AI&#xff09;的众多应用中&#xff0c;去衣技术作为一种新兴的图像处理技术&#xff0c;逐渐引起了广泛关注。这项技术不仅涉及复杂的计算机视觉和深度学习算法&#xff0c;还需要对图像处理中的插值与重采样技术有深入的理解。本文将详细探讨插值与重…

【笔试训练】day7

1.在字符串中找出连续最长的数字串 思路&#xff1a; 简单双指针&#xff0c;随便怎么暴力 代码&#xff1a; #define _CRT_SECURE_NO_WARNINGS 1 #include <iostream> #include<string> using namespace std;int main() {string str;cin >> str;int ans …

微服务之SpringCloud AlibabaNacos服务注册和配置中心

一、概述 1.1注册中心原理 在微服务远程调用的过程中&#xff0c;包括两个角色&#xff1a; 服务提供者&#xff1a;提供接口供其它微服务访问&#xff0c;比如item-service 服务消费者&#xff1a;调用其它微服务提供的接口&#xff0c;比如cart-service 在大型微服务项目…

Laya2.13.3 Texture和Teture2D的关系,怎样将Texture2D转换为Texture。

Texture是是纹理处理类&#xff0c;Sprite和Image上显示的图像都是经Texture处理的&#xff0c; Texture2D是3d模型纹理贴图的处理类&#xff0c;用于显示3D模型的纹理细节。 如何将Textture2D转换为Texture&#xff0c;Texture的API接口如下&#xff1a; 可以看到Texture首先…

STM32 | USART实战案例

STM32 | 通用同步/异步串行接收/发送器USART带蓝牙(第六天)随着扩展的内容越来越多,很多小伙伴已经忘记了之前的学习内容,然后后面这些都很难理解。STM32合集已在专栏创建,方面大家学习。1、通过电脑串口助手发送数据,控制开发板LED灯 从题目中可以挖掘出,本次使用led、延…

vscode 配置verilog环境

一、常用的设置 1、语言设置 安装如下插件&#xff0c;然后在config 2、编码格式设置 解决中文注释乱码问题。vivado 默认是这个格式&#xff0c;这里也设置一样。 ctrl shift p 打开设置项 3、插件信任区设 打开一个verilog 文件&#xff0c;显示是纯本文&#xff0c;没…

HarmonyOS开发环境搭建 移动开发 鸿蒙开发 ArkTS

&#x1f4dc;目录 &#x1f4a1; 环境搭建 &#x1f680;安装nodejs &#x1f935;安装ohpm &#x1f354;安装SDK &#x1f4a5;Emulator安装 &#x1f336;️新建ArkTs项目 &#x1f3c6;️ArkTS语言 ✨️基本语法 &#x1f388; 声明式UI描述 &#x1f371;组件 …

使用spring boot集成shardingsphere分库分表简易测试

根据如下pom整上一个spring-boot项目&#xff0c;spring-boot版本用2.3.5&#xff0c;shardingsphere用5.1.1。 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://ww…

【KingSCADA】通过地址引用和弹窗模板实现设备控制

当相同的设备过多时&#xff0c;要做很多相同的弹窗&#xff0c;这种情况下可以通过地址引用和弹窗模板实现设备控制。 1.变量创建 2.画面开发 以阀门控制为例&#xff0c;只需要做一个阀门控制界面模板 3.地址引用 # 4.实现效果

Linux基本命令之正则表达式(转义字符)

一&#xff1a;查看二进制文件 strings 命令&#xff1a;strings 文件名 生成链接文件 ln 命令&#xff1a;ln 选项 源文件(f1) 链接文件&#xff08;f2&#xff09; 软连接&#xff1a;eg:ln -s f1 f2 软链接不能跨分区链接&#xff0c;但可以在同一分区的不同目录下链接…

小型架构实验模拟

一 实验需求 二 实验环境 22 机器&#xff1a; 做nginx 反向代理 做静态资源服务器 装 nginx keepalived filebeat 44机器&#xff1a; 做22 机器的备胎 装nginx keepalived 99机器&#xff1a;做mysql的主 装mysqld 装node 装filebeat 77机器&#xff1a;做mysq…

目标检测网络YOLO进化之旅

yolo系列网络在目标检测领域取得了巨大的成功&#xff0c; 尤其是在工程实践中&#xff0c; 以其出色的性能优势获得了广泛的应用落地。 YOLO的前3个版本是由同一个作者团队出品&#xff0c; 算是官方版本。 之后的版本都是各个研究团队自己改进的版本&#xff0c; 之间并无明…

Linux 安装 Docker +Docker Compose + cucker/get_command_4_run_container

TIP&#xff1a;下面演示的 Linux 系统为 CentOS 7.9。 Docker 更新你的系统并安装必要的依赖项&#xff1a; sudo yum update -y sudo yum install -y yum-utils device-mapper-persistent-data lvm2添加 Docker 的官方仓库&#xff1a; sudo yum-config-manager --add-rep…