操作系统:Windows8.1

显卡:Nivida GTX965M

开发工具:Unity2017.3 | Shader


最近在制作一款APP,其中需要对矩形图片资源的展现进行圆角化,看了一下网上的方案大多是基于正方形,然而在实际场景中,需要圆角化的图片往往还包括矩形,即宽高不相等,如果用技术参数来解释,便是 widthheightaspect 1。所以本文将会简要说明如何实现矩形圆角化Shader。

首先看下效果组图。

通过图示我们观察到,常规的基于正方形体的圆角化效果基本符合我们预期,即当半径达到 0.50 最大值的时候变成了圆形。除此之外,长方形虽然围绕Y方向进行了一定程度的拉伸 (在这里高度为宽度的2倍),但算法对中心点进行了修正,最终确保了正确的圆角化效果。

Basic Conception


效果已经看完了,那么如何设计实现呢,我们在这里将圆角化分两个部分阐述原理。首先了解基于正方形的圆角化思路。如下图所示,如果选择上下左右四个角作为圆角化目标,则分别需要按照上下左右四个圆形区域进行mask渲染,最终只保留图示中绿色区域及黄色区域。如下图所示,当 半径 r = 0.25 时及 r = 0.5 时圆角化处理后的保留渲染区域,特别的当r= 0.5时可以联想四个角度区域的原型发生了重叠。

在继续深入讨论实现之前,我们温习一下UV坐标系,这是在贴图采样过程中遵循的坐标系,具体如下图所示:

UV坐标范围是收敛在 [0, 1] 之间,如果当前UV坐标是 (0.1, 0.1) 取得颜色值是绿色,如果当前UV坐标是 (0.2, 0.8) 取得颜色值就是粉色,如果当前UV值是 (0.7, 0.2) 取得颜色值就是蓝色,如果当前UV值是 (0.9, 0.9) 取得颜色值就是黄色。如果要索取更多的信息可以进入 WIKI咨询。

搞清概念后,我们只需要简单的在Shader中针对四个方向分别定义圆点,并根据圆点坐标及半径来判断当前UV是否在圆半径范围内,如果在圆半径范围内应用采样,反之填充透明色或者丢弃当前片元。几个主要代码片段如下:

shader中定义新的变量用于保存自定义半径信息,在这里默认为0.25

Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Radius ("_Radius", Range(0, 0.5)) = 0.25
}

同时片段着色器编写主要判定逻辑,如下:

fixed4 frag (v2f i) : SV_Target
{
// UV采样数据
fixed4 col = tex2D(_MainTex, i.uv);
// 用于保存像素与圆心距离
half dist = 0;
// 默认圆心坐标
half2 center = half2(0, 0);
// 默认右上角圆心坐标
half2 TRC = half2(1, 1);
// 默认右下角圆心坐标
half2 BRC = half2(1, 0);
// 默认左下角圆心坐标
half2 BLC = half2(0, 0);
// 默认左上角圆心坐标
half2 TLC = half2(0, 1); // 根据输入半径修正右上角圆心坐标
center = half2(TRC.x - _Radius, TRC.y - _Radius);
if (true)
{
// 判定当前UV是否在圆外侧
if (center.x < i.uv.x && center.y < i.uv.y)
{
// 计算当前UV点与圆心距离
dist = sqrt(
  pow(center.x - i.uv.x, 2)
  +
  pow(center.y - i.uv.y, 2)
  ); // 将距离与圆半径比较,如果不在范围内,丢弃该片段
if (dist > _Radius)
{
discard;
}
}
} return col;
}

该代码已经在注释中描述的比较清晰了,没有说清楚的是一个 if (true) 语句,该语句用于通过外部传递的信息决定是否对当前角进行圆角化处理。主要更新代码如下:

Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Radius ("_Radius", Range(0, 0.5)) = 0.25 [MaterialToggle] _TR ("_TopRightCorner", Float) = 1
[MaterialToggle] _BR ("_BottomRightCorner", Float) = 1
[MaterialToggle] _BL ("_BottomLeftCorner", Float) = 1
[MaterialToggle] _TL ("_TopLeftCorner", FLoat) = 1

}

将开关变量分别替换掉 if(true) 后运行程序,如果一切顺利,运行效果如下图所示。

通过图示我们看到已经可以通过编辑材质来控制图片资源的圆角显示规则了。

Rectangle implementation


矩形的圆角化功能是基于上文正方形圆角化功能扩展的,所谓扩展的点就在于利用非 1 : 1 的宽高比进行已有算法实现的修正,看起来有点难以理解,没有关系,我们看代码说话。

// 修正圆心X坐标位置
half sfx0 = 1;
// 修正UV点与圆心距离
half sfx1 = 1;
// 修正圆心Y轴坐标位置
half sfy0 = 1;
// 修正UV点与圆心距离
half sfy1 = 1; // 当矩形的width > height 时计算圆心、UV修正系数
if (_scale.x > _scale.y)
{
// 计算UV坐标空间下,圆心X坐标对应缩放系数
sfx0 = _scale.y/_scale.x;
sfx1 = (_scale.y/ pow(_scale.x,2));
}
else
{
// 计算UV坐标空间下,圆心Y坐标对应缩放系数
sfy0 = _scale.x/_scale.y;
sfy1 = (_scale.x/ pow(_scale.y,2));
}

同时圆角化用于计算圆心到UV采样点的距离需要根据缩放的比例进行调整,具体代码如下。

center = half2((_TRC.x - (_Radius * sfx0)),(_TRC.y - (_Radius * sfy0) ));
if (_TR == 1 )
{
  if (center.x < IN.texcoord.x && center.y < IN.texcoord.y)
  {
    dist = sqrt( pow( center.x - IN.texcoord.x , 2 ) / sfx1 + pow( center.y - IN.texcoord.y , 2 ) / sfy1);     if (dist > _Radius)
    {
      discard;
    }
  }
}

如果一些顺利,将该部分修改更新到四个圆角计算部分,最后通过外部传递参数控制即可,在这里以Unity3D材质编辑属性为例,输入图片资源的缩放比例即可。

Summary


整体的实现思路还是比较清晰的,在实际使用中如果结合UGUI的ScrollView子元素,可能出现遮罩的问题,只要将模版缓冲区相关的Shader设置代码补全即可。

[ShaderStaff] 圆角矩形效果实现的更多相关文章

  1. 不使用border-radius,实现一个可复用的高度和宽度都自适应的圆角矩形

    现在css3支持圆角矩形,但是为了兼容性问题,虽然比较麻烦,但还是有必要了解一下以下方法. 在一个div内,包含8个div,控制这个8个div的height.margin以及border属性值,以达到 ...

  2. C# vb .net实现圆角矩形特效滤镜

    在.net中,如何简单快捷地实现Photoshop滤镜组中的圆角矩形效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第 ...

  3. Android中实现圆角矩形及半透明效果。

    注:本文由Colin撰写,版权所有!转载请注明原文地址,谢谢合作! 在做Android开发时,我们为了美观,有时候需要使用圆角矩形,或半透明之类的效果,在网页设计中很容易实现.但在Android开发中 ...

  4. [BOT] 一种android中实现“圆角矩形”的方法

    内容简介 文章介绍ImageView(方法也可以应用到其它View)圆角矩形(包括圆形)的一种实现方式,四个角可以分别指定为圆角.思路是利用"Xfermode + Path"来进行 ...

  5. 一行实现QQ群组头像,微信群组,圆角等效果. 并支持url直接加载图片

    说点题外话. Coding中我们总是经历着这么几个过程. 学会使用: 不管是API也好, 开源库也好. 总是在最开始的学会去用. 了解实现原理: 可能会因为一些不兼容, 代码的异常状态的处理不够完美等 ...

  6. RoundedImageView,实现圆形、圆角矩形的注意事项

    RoundedImageView是gitHub上面的一个开源组件(https://github.com/vinc3m1/RoundedImageView),实现一些圆形或者圆角矩形是很方便的, < ...

  7. Android圆角矩形创建工具RoundRect类

    用于把普通图片转换为圆角图像的工具类RoundRect类(复制即可使用): import android.content.Context; import android.graphics.Bitmap ...

  8. 解读Unity中的CG编写Shader系列四(unity中的圆角矩形shader)

    转自 http://www.itnose.net/detail/6097625.html 上篇文章中我们掌握了表面剔除和剪裁模式 这篇文章将利用这些知识实现一个简单的,但是又很常用的例子:把一张图片做 ...

  9. Android利用canvas画各种图形(点、直线、弧、圆、椭圆、文字、矩形、多边形、曲线、圆角矩形) .

    1.首先说一下canvas类: Class Overview The Canvas class holds the "draw" calls. To draw something, ...

随机推荐

  1. 快速理解 FastCGI、PHP-CGI、PHP-FPM

    你(PHP)去和泰国人(web服务器,如 Apache.Nginx)谈生意 你说中文(PHP代码),他说泰语(C代码),互相听不懂,怎么办?那就都把各自说的话转换成英语(FastCGI 协议)吧. 怎 ...

  2. Java9新特性

    转载:http://blog.csdn.net/qq_32524177/article/details/77014757 写在前面的话:Java9来了,搜索了很多关于Java9的新特性,但文献不多,特 ...

  3. Windows 7 IIS7.5上部署MVC实例

    这段时间在用MVC写一个导游网站,在Window7上部署的时候,遇到和处理了一些问题. 现将完整的过程整理出来,供大家参考: 一.部署准备: 1.安装Microsoft .net FrameWork ...

  4. MVC Ajax Helpers

    在MVC中要实现Ajax有很多的方式,有微软自己的MicrosoftAjax,也可以用JQuery的AJax来实现,如果对其他的JavaScript框架熟悉,还可以采用其他的实现方案,比如说Proto ...

  5. 2018.12.4 王二的经济学故事 DYNASTIES

    1从王二卖粮食:外汇储备缩水 2王二兑酒:固定汇率与变动汇率 3苹果换梨子:固定汇率的代价 4跨港购物:一价定律,汇率的价格传递效应 5富人吃透,春运火车票涨价:供需问题,弱者保护,让富人多消费,给穷 ...

  6. New Concept English Two 27 73

    新概念一:对应小学水平,重在口语和基础.是不可多得的学习教材,全本144课,可以给孩子(hello world 级别的我)学半年.新概念二:对应高中水平,重在听力和场景对话,共96课,学后,听懂歪果仁 ...

  7. 二叉树的前序、中序、后序遍历 python

    话不多说,直接上代码 class TreeNode: def __init__(self, x): self.val = x self.left = None self.right = None cl ...

  8. sysfs文件系统学习--sysfs

    一.sysfs简介1.sysfs就是利用VFS的接口去读写kobject的层次结构,建立起来的文件系统.其更新与删除是那些xxx_register()/unregister()做的事 情.从sysfs ...

  9. ringojs 的包管理

    ringojs 集成了包管理目前有几种方式 ringo-admin rp ringo-admin 安装包 我们使用ringo-admin 安装rp ringo-admin install grob/r ...

  10. mschart 使用心得和部署。

    参考: http://www.cnblogs.com/suguoqiang/archive/2013/01/16/2862945.html 1.在统计时可能需要多条数据,需要整合数据源 Chart1. ...