操作系统: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

  1. Properties
  2. {
  3. _MainTex ("Texture", 2D) = "white" {}
  4. _Radius ("_Radius", Range(0, 0.5)) = 0.25
  5. }

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

  1. fixed4 frag (v2f i) : SV_Target
  2. {
  3. // UV采样数据
  4. fixed4 col = tex2D(_MainTex, i.uv);
  5. // 用于保存像素与圆心距离
  6. half dist = 0;
  7. // 默认圆心坐标
  8. half2 center = half2(0, 0);
  9. // 默认右上角圆心坐标
  10. half2 TRC = half2(1, 1);
  11. // 默认右下角圆心坐标
  12. half2 BRC = half2(1, 0);
  13. // 默认左下角圆心坐标
  14. half2 BLC = half2(0, 0);
  15. // 默认左上角圆心坐标
  16. half2 TLC = half2(0, 1);
  17.  
  18. // 根据输入半径修正右上角圆心坐标
  19. center = half2(TRC.x - _Radius, TRC.y - _Radius);
  20. if (true)
  21. {
  22. // 判定当前UV是否在圆外侧
  23. if (center.x < i.uv.x && center.y < i.uv.y)
  24. {
  25. // 计算当前UV点与圆心距离
  26. dist = sqrt(
  27.   pow(center.x - i.uv.x, 2)
  28.   +
  29.   pow(center.y - i.uv.y, 2)
  30.   );
  31.  
  32. // 将距离与圆半径比较,如果不在范围内,丢弃该片段
  33. if (dist > _Radius)
  34. {
  35. discard;
  36. }
  37. }
  38. }
  39.  
  40. return col;
  41. }

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

  1. Properties
  2. {
  3. _MainTex ("Texture", 2D) = "white" {}
  4. _Radius ("_Radius", Range(0, 0.5)) = 0.25
  5.  
  6. [MaterialToggle] _TR ("_TopRightCorner", Float) = 1
  7. [MaterialToggle] _BR ("_BottomRightCorner", Float) = 1
  8. [MaterialToggle] _BL ("_BottomLeftCorner", Float) = 1
  9. [MaterialToggle] _TL ("_TopLeftCorner", FLoat) = 1
  10. }

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

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

Rectangle implementation


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

  1. // 修正圆心X坐标位置
  2. half sfx0 = 1;
  3. // 修正UV点与圆心距离
  4. half sfx1 = 1;
  5. // 修正圆心Y轴坐标位置
  6. half sfy0 = 1;
  7. // 修正UV点与圆心距离
  8. half sfy1 = 1;
  9.  
  10. // 当矩形的width > height 时计算圆心、UV修正系数
  11. if (_scale.x > _scale.y)
  12. {
  13. // 计算UV坐标空间下,圆心X坐标对应缩放系数
  14. sfx0 = _scale.y/_scale.x;
  15. sfx1 = (_scale.y/ pow(_scale.x,2));
  16. }
  17. else
  18. {
  19. // 计算UV坐标空间下,圆心Y坐标对应缩放系数
  20. sfy0 = _scale.x/_scale.y;
  21. sfy1 = (_scale.x/ pow(_scale.y,2));
  22. }

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

  1. center = half2((_TRC.x - (_Radius * sfx0)),(_TRC.y - (_Radius * sfy0) ));
  2. if (_TR == 1 )
  3. {
  4.   if (center.x < IN.texcoord.x && center.y < IN.texcoord.y)
  5.   {
  6.     dist = sqrt( pow( center.x - IN.texcoord.x , 2 ) / sfx1 + pow( center.y - IN.texcoord.y , 2 ) / sfy1);
  7.  
  8.     if (dist > _Radius)
        {
  9.       discard;
  10.     
  11.   }
  12. }

如果一些顺利,将该部分修改更新到四个圆角计算部分,最后通过外部传递参数控制即可,在这里以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. iOS UI-自动布局(Autoresizing)

    // // ViewController.m // IOS_0115_buzhi // // Created by ma c on 16/1/15. // Copyright (c) 2016年 博文 ...

  2. java并发编程:线程安全管理类--原子操作类--AtomicIntegerArray

    1.类 AtomicIntegerArray

  3. Uedit个人专注

    Uedit个人专注   Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOT\*\Shell\Uedit] [HKEY_CLASSES_ROO ...

  4. 201621123006 《Java程序设计》第7周学习总结

    1. 本周学习总结 1.1 思维导图:Java图形界面总结 1.2 可选:使用常规方法总结其他上课内容. 窗体事件:一般做最外层容器 鼠标事件:按下.松开.单击 键盘事件:按下.释放 动作事件:不代表 ...

  5. 使用c++实现一个FTP客户端(一)

    之前使用c++实现了一个FTP客户端,在这里做一些记录. 一.需要注意的几点 ①FTP是一种文件传输协议,基于TCP,所以客户端与服务器建立的连接是可靠.安全的,并且要经过三次握手的过程. ②FTP传 ...

  6. CentOS怎样安装Python3.6

    yum install -y openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel安装可能用到的依赖 ...

  7. 结合File类浅析递归的使用

    递归算法就是方法自身直接或者间接地调用到了自身,它是一种写起来很简单,但理解起来不那么简单的算法. 一个功能在被重复地调用,并且运算的结果和上一次的调用有关, 这种时候,可以使用递归. * 注意: * ...

  8. 《DSP using MATLAB》示例 Example 9.11

    代码: %% ------------------------------------------------------------------------ %% Output Info about ...

  9. [LOJ6198]谢特

    loj description 给你一个字符串和一个数组\(w_i\),定义\(\mbox{LCP}(i,j)\)为\(i,j\)两个后缀的最长公共前缀.求\(\max_{i,j}\mbox{LCP} ...

  10. 使用IAR编译STM8S 怎样生产烧录文件

      IAR编译后能够生成的烧录文件格式有4中,例如以下 第一种是Motorola,其生成文件和STVD生成烧录文件.s19格式一样的,即能够通用 另外一种是16进制,keil等等常都用到的. 第三种是 ...