上篇文章中我们掌握了表面剔除和剪裁模式

这篇文章将利用这些知识实现一个简单的,可是又非经常常使用的样例:把一张图片做成圆角矩形

例3:圆角矩形Shader

好吧我承认在做这个样例的时候走了不少弯路,因为本人对矩阵的知识掌握已经悉数还给老师,所以一開始用了一些笨办法计算圆角矩形区域。

我们知道TEXTCOORD0是一个以对象为坐标系的坐标,而且范围在该坐标的第一象限,取值为(0,0)到(1,1)

那么我们把每一张图片都看做一张1X1大小的矩形

我们要在1X1大小的矩形中擦除4个角,应该是这样:

以左上角为例,我们做一个辅助圆内切于这个角,半径为0.1,那么我们将这个圆擦掉3/4,剩下的黄色弧线与这个角形成的区域就是我们要擦除的区域:

这个道理非常easy,那么我们对4个角分别擦除掉这种区域就能得到一个半径为10%原图尺寸的圆角矩形

我一開始走的弯路就在于计算这个区域,是用4个圆的方程来算呢还是用距离来计算

因为给出4个圆的方程太过于复杂,我这里直接给出计算外点距离算法的示意图:

首先在这个大矩形的内部以4个圆心为顶点做出一个内矩形,心算得边长为0.8

其次忽略内矩形内部的点,在这个红色矩形内给定随意一个蓝色矩形的外点p  ,仅仅要可以得到p到蓝色矩形的距离,距离大于0.1(半径),那么就在圆角矩形外部,直接擦除,如图:

我们看p1,p2,p3,3个点到蓝色矩形的距离各自是p1的距离<半径,根号2倍半径>p2的距离>半径,p3的距离等于半径

所以p2在圆角矩形外,p1,p3在圆角矩形内部或边缘,我们将p2擦除掉

当中p3的距离恰好是 p3到4条直线的距离最小值

p1同理

而p2的距离不能再这样计算,而应该是计算p2到4个顶点距离的最小值

按这个算法仅仅要算出全部外点中的点到蓝色矩形区域的距离,然后与半径推断大小,大于则discard就能得到圆角矩形

一開始我依照这个思路得出一个极端无脑的方法:

给定随意一点p,求p到4条直线,4个顶点的距离,然后在8个距离中求最小值作为终于的距离拿来与半径比較

兴奋地写完代码知道我错了,检查了非常久才明确,像p3这样的点,算出来的8个距离中,最小距离并非到顶点的距离,而是到两条边的延长线的距离

于是终于8距离求最小值算法以失败告终

还是得老老实实分情况

那么有几种情况呢

事实上仅仅有1种,可是先按正常逻辑分为2种:

我们来看绿色区域和紫色区域的外点们

1、当外点在紫色区域时,距离应是点到4顶点的距离最小值

2、当外点在绿色区域时,距离应是点到4条直线的距离最小值

依照这个思路那么我们能够对整个 坐标系内的随意点(x,y)进行推断:

1、假设点在白色区域或者绿色区域内,  还计算个毛线距离啊,肯定是不discard啊~~~~(之前我傻乎乎的还真去算了)

2、紫色区域内计算点到4顶点距离,然后取最小值,然后将大于0.1的部分剔除掉

最后我们须要将这个0.1作为变量提取出来,不能写死,这样能够在Inspector中方便调节,或者在script中去设置,也就是给我们的shader定义一个float或rang型的属性

最后代码为:

  1. Shader "Custom/RoundRect" {
  2. Properties {
  3. //两种内容模式,图片模式
  4. _MainTex ("Base (RGB)", 2D) = "white" {}
  5. //纯色模式
  6. //_MainColor ("Color", COLOR) = (1,1,1,1)
  7. //圆角半径,默觉得0.1
  8. _RoundRadius("Radius",float) = 0.1
  9. }
  10. SubShader {
  11.  
  12. Pass{
  13. CGPROGRAM
  14.  
  15. #pragma fragment frag
  16.  
  17. #include "UnityCG.cginc"
  18. //获取3个属性 并传值到CG代码段
  19. sampler2D _MainTex;
  20. float _RoundRadius;
  21. float4 _MainColor;
  22.  
  23. //片段着色器输入结构体(可省略)
  24. struct FragInput{
  25. float2 texcoord:TEXCOORD0;
  26.  
  27. };
  28.  
  29. //片段着色器入口函数
  30. float4 frag(FragInput input) : COLOR
  31. {
  32.  
  33. float4 c=tex2D(_MainTex,input.texcoord);//将图片信息按坐标转换成颜色
  34. //float4 c=_MainColor; //纯色
  35.  
  36. //x,y两个变元,区间均为[0,1]
  37. float x=input.texcoord.x;
  38. float y=input.texcoord.y;
  39.  
  40. //4条直线的常数部分
  41. float xt=1-_RoundRadius;
  42. float xb=_RoundRadius;
  43. float yl=_RoundRadius;
  44. float yr=1-_RoundRadius;
  45. //假设(x,y)不在4条直线构成的矩形中(上图的白色区域)
  46. if(!(x<xt&&x>xb&&y>yl&&y<yr))
  47. {
  48.  
  49. //假设(x.y)不在上图的绿色区域
  50. if(!((x<xt&&x>xb) || (y>yl&&y<yr) ))
  51. //数学不好,好像推断的复杂了,假设您能够直接写出紫色区域
  52. //的不等式组那么能够简单点
  53. {
  54. //计算四个顶点的坐标
  55. float2 plb=float2(_RoundRadius,_RoundRadius);
  56. float2 plt=float2(_RoundRadius,1-_RoundRadius);
  57. float2 prt=float2(1-_RoundRadius,1-_RoundRadius);
  58. float2 prb=float2(1-_RoundRadius,_RoundRadius);
  59.  
  60. //计算x,y分别到4个顶点的距离
  61. float distlb=sqrt(pow((x-plb.x),2)+pow((y-plb.y),2));
  62. float distlt=sqrt(pow((x-plt.x),2)+pow((y-plt.y),2));
  63. float distrt=sqrt(pow((x-prt.x),2)+pow((y-prt.y),2));
  64. float distrb=sqrt(pow((x-prb.x),2)+pow((y-prb.y),2));
  65.  
  66. //对4个距离取最小值
  67. float dist=min(distlb,distlt);
  68. dist=min(dist,distrt);
  69. dist=min(dist,distrb);
  70.  
  71. //将大于半径的表面剔除
  72. if(dist>_RoundRadius)
  73. discard;
  74.  
  75. }
  76.  
  77. }
  78.  
  79. return c;
  80.  
  81. }
  82. ENDCG
  83. }
  84.  
  85. }
  86. FallBack "Diffuse"
  87. }

最后执行的效果,不同Radius不同尺寸的图片进行圆角矩形剔除

当radius设为0.25时我们能够得到一个圆,所以我们的RoundRadius属性能够设置为一个0.01~0.25的rang

因为我是windows系统,mac os下好像有点问题,不知道是不是省略了顶点着色器的问题,发现原因后再来补正

假设我的博客对您有帮助或者您有不论什么疑问,欢迎增加重庆u3d交流QQ群我会给您解答:68994667,也能够加群与我们一同交流技术

解读Unity中的CG编写Shader系列4——unity中的圆角矩形shader的更多相关文章

  1. [转]解读Unity中的CG编写Shader系列7——漫反射

    如果前面几个系列文章的内容过于冗长缺乏趣味着实见谅,由于时间原因前面的混合部分还没有写完,等以后再补充,现在开始关于反射的内容了.折射与反射在物理世界中,光的反射与折射往往是同时存在的,光源由真空或者 ...

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

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

  3. [转]解读Unity中的CG编写Shader系列4——unity中的圆角矩形shader

    上篇文章中我们掌握了表面剔除和剪裁模式这篇文章将利用这些知识实现一个简单的,但是又很常用的例子:把一张图片做成圆角矩形 例3:圆角矩形Shader好吧我承认在做这个例子的时候走了不少弯路,由于本人对矩 ...

  4. 解读Unity中的CG编写Shader系列八(镜面反射)

    转自http://www.itnose.net/detail/6117378.html 讨论完漫反射之后,接下来肯定就是镜面反射了 在开始镜面反射shader的coding之前,要扩充一下前面提到的知 ...

  5. [转]解读Unity中的CG编写Shader系列9——镜面反射

    讨论完漫反射之后,接下来肯定就是镜面反射了在开始镜面反射shader的coding之前,要扩充一下前面提到的知识,加深理解镜面反射与漫反射的区别.注:这篇文章实现的镜面反射是逐顶点着色(per-ver ...

  6. unity 切圆角矩形 --shader编程

    先上个效果图 制作思路 如上图我们要渲染的就是上图带颜色的部分 步骤: 先获取黄色和蓝绿部分 例如以下图 算法 |U|<(0.5-r)或|V|<(0.5-r) 注意的是模型贴图最大值是1. ...

  7. 圆角矩形shader

    在游戏中,有时需要对一张矩形图片进行切割,绘制成圆角矩形. circelrect.vert attribute vec4 a_position; attribute vec4 a_normal; at ...

  8. 解读Unity中的CG编写Shader系列十 (光滑的镜面反射(冯氏着色))

    前文完成了最基本的镜面反射着色器,单平行光源下的逐顶点着色(per-vertex lighting),又称为古罗着色(Gouraud shading).这篇文章作为后续讨论更光滑的镜面反射方式,逐像素 ...

  9. 解读Unity中的CG编写Shader系列七(不透明度与混合)

    转自http://www.itnose.net/detail/6098539.html 1.不透明度 当我们要将两个半透的纹理贴图到一个材质球上的时候就遇到混合的问题,由于前面的知识我们已经知道了片段 ...

随机推荐

  1. C# Adding Hyperlink to Windows Form z

    When creating a Windows form in C#, we would like to create a hyperlink so that when the user click ...

  2. Delphi中编辑word

      其他(28)   //启动Word   try     wordapplication1.connect;   except     messagedlg('word may not be ins ...

  3. poj 1505 Copying Books

    http://poj.org/problem?id=1505 Copying Books Time Limit: 3000MS   Memory Limit: 10000K Total Submiss ...

  4. <转>数据库设计的三大范式

    为了建立冗余较小.结构合理的数据库,设计数据库时必须遵循一定的规则.在关系型数据库中这种规则就称为范式.范式是符合某一种设计要求的总结.要想设计一个结构合理的关系型数据库,必须满足一定的范式. 在实际 ...

  5. 跟我学机器视觉-HALCON学习例程中文详解-FUZZY检测用于开关引脚测量

    跟我学机器视觉-HALCON学习例程中文详解-FUZZY检测用于开关引脚测量 * This example program demonstrates the basic usage of a fuzz ...

  6. mysql 中的外键key值的详解

    如果Key是空的, 那么该列值的可以重复, 表示该列没有索引, 或者是一个非唯一的复合索引的非前导列2. 如果Key是PRI,  那么该列是主键的组成部分3. 如果Key是UNI,  那么该列是一个唯 ...

  7. (转载)OC学习篇之---概述

    前言 终于开启了OC的学习篇了,之前由于工作上的事,学习就一直搁浅了,不过最近由于各种原因,感觉必须要开启iOS的开发旅程了,不然就老了.因为之前一直是做Android的,所以学习iOS来就没那么费劲 ...

  8. 在Windows上,如何卸载RabbitMQ服务

    打开运行->CMD->sc delete RabbitMQ 如果报错..... 打开运行->regedit 找到RabbitMQ节点,删掉即可.(右侧看到的都是启动服务时,需要的配置 ...

  9. ubuntu下修改时区

    使用一个虚拟机服务,其时区设置的为格林兰标准时区,我北京时区在东八区,较其快八个小时. 修改时区需要执行 tzselect 一步步选择下来,注意确认后的information Therefore TZ ...

  10. HDU 5776 sum (模拟)

    sum 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5776 Description Given a sequence, you're asked ...