先上个效果图


Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_unity shader圆角矩形


制作思路


Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_#include_02

如上图我们要渲染的就是上图带颜色的部分

步骤:

先获取黄色和蓝绿部分

如下图

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_unity shader圆角矩形_03


算法

|U|<(0.5-r)或|V|<(0.5-r)

注意的是模型贴图最大值是1.


然后获取红色的四份之一圆部分


实现过程

首先在unity里创建一个shader。

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_#include_04

创建完成后

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_unity shader圆角矩形_05

然后双击newshader(名字是可以随便起)

将里面的内容全部删掉

代码如下:

Shader "Custom/NewShader" {
     Properties {
         _MainTex ("Base (RGB)", 2D) = "white" {}
     }
     SubShader
     {
         pass
         {
         
         CGPROGRAM
         #pragma vertex vert
         #pragma fragment frag
         #include "unitycg.cginc"
         sampler2D _MainTex;
         struct v2f
         {
         float4 pos : SV_POSITION ;
         float2 ModeUV: TEXCOORD0;
         };
         v2f vert(appdata_base v)
         {
         v2f o;
         o.pos=mul(UNITY_MATRIX_MVP,v.vertex);  //将模型顶点坐标转换到视图坐标矩阵中
         o.ModeUV=v.texcoord;   //获取模型的UV坐标
         return o;
         }
         fixed4 frag(v2f i):COLOR
         {
         fixed4 col;
         
         col=tex2D(_MainTex,i.ModeUV);      //根据模型UV坐标获取贴图相对应的颜色
         
         return col;        
         }
         ENDCG
         
         }
     }
 }

 


上述主要代码以注释。现在实现了一个简单的顶点像素shader。

然后建一个material材质球,将你写的shader拖到material上面去,然后给material赋值一张图片。

然后创建一个3D的Plane物体,将material拖到物体上面去。


效果如下图:

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_#include_06

好了现在我们来切圆角矩形。

要说明的是我们为了计算方便坐标系原点在uv的中心,但是unity模型的uv的原点在左下角如下图,切vu取值范围(0,1)。就是说贴图的像素坐标也是(0,1)表示所有的像素坐标点

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_#include_07

unity的uv坐标系

所以为了统一,我们将unity的uv坐标系处理成中心坐标系,用一个变量存储处理后的坐标系

方法是

unity的uv-float(0.5,0.5)

首先我们实现下图区域的显示

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_unity shader圆角矩形_03


修改上面的代码,我们需要添加一个圆角半径的属性,然后我们要获取上面所说的黄色和蓝绿色部分,添加代码下面红色字体。代码修改后如下:

Shader "Custom/NewShader" { 

Properties { 

_MainTex ("Base (RGB)", 2D) = "white" {} 

 
_RADIUSBUCE("_RADIUSBUCE",Range(0,0.5))=0.2 

} 

SubShader 

{ 

pass 

{ 

 

CGPROGRAM 


#pragma exclude_renderers gles 

#pragma vertex vert 

#pragma fragment frag 

#include "unitycg.cginc" 

 
float _RADIUSBUCE; 

sampler2D _MainTex; 



struct v2f 

{ 

float4 pos : SV_POSITION ; 

float2 ModeUV: TEXCOORD0; 

 
float2 RadiusBuceVU : TEXCOORD1; 

}; 

v2f vert(appdata_base v) 

{ 

v2f o; 

o.pos=mul(UNITY_MATRIX_MVP,v.vertex); //v.vertex; 

o.ModeUV=v.texcoord; 

 
o.RadiusBuceVU=v.texcoord-float2(0.5,0.5);       //将模型UV坐标原点置为中心原点,为了方便计算 



return o; 

} 





fixed4 frag(v2f i):COLOR 

{ 

fixed4 col; 

col=(0,1,1,0); 



if(abs(i.RadiusBuceVU.x)<0.5-_RADIUSBUCE||abs(i.RadiusBuceVU.y)<0.5-_RADIUSBUCE)    //即上面说的|x|<(0.5-r)或|y|<(0.5-r)
{

col=tex2D(_MainTex,i.ModeUV);


} 

 

return col; 
  

} 

ENDCG 

 

} 

} 

 }


效果如下图:

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_#include_09



好了现在我们开始获取红色四份之一圆区域

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_#include_02

继续修改代码(蓝色字体)


Shader "Custom/NewShader" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_RADIUSBUCE("_RADIUSBUCE",Range(0,0.5))=0.2
}
SubShader
{
pass
{

CGPROGRAM

#pragma exclude_renderers gles
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
float _RADIUSBUCE;
sampler2D _MainTex;


struct v2f
{
float4 pos : SV_POSITION ;
float2 ModeUV: TEXCOORD0;
float2 RadiusBuceVU : TEXCOORD1;
};
v2f vert(appdata_base v)
{
v2f o;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex); //v.vertex;
o.ModeUV=v.texcoord;
o.RadiusBuceVU=v.texcoord-float2(0.5,0.5);       //将模型UV坐标原点置为中心原点,为了方便计算


return o;
}




fixed4 frag(v2f i):COLOR
{
fixed4 col;
col=(0,1,1,0);


if(abs(i.RadiusBuceVU.x)<0.5-_RADIUSBUCE||abs(i.RadiusBuceVU.y)<0.5-_RADIUSBUCE)    //即上面说的|x|<(0.5-r)或|y|<(0.5-r)
{

col=tex2D(_MainTex,i.ModeUV);


}
else
{
if(length( abs( i.RadiusBuceVU)-float2(0.5-_RADIUSBUCE,0.5-_RADIUSBUCE)) <_RADIUSBUCE)
{
col=tex2D(_MainTex,i.ModeUV);

}
else
{
discard;
} 
}
return col;  
}
ENDCG

}
}
 }

这是在以前的代码的基础上添加了else分支判断。

逻辑顺序是这样的 if判断的是下图区域的,else就是非下图区域的其他区域

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_unity shader圆角矩形_03

if判断的区域

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_#include_12

else区域(蓝色框的区域)

然后我们在else下再判断像素点是否在四份之一圆呢就行了

if(length( abs( i.RadiusBuceVU)-float2(0.5-_RADIUSBUCE,0.5-_RADIUSBUCE)) <_RADIUSBUCE)

上面这句判断有点乱

首先我们先获取UV坐标u和v都是正半轴的四份之一圆:下面蓝色框区域。

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_unity切圆角矩形_13

首先我们获取下图p点坐标

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_#pragma_14

即:p=float2(0.5-_RADIUSBUCE,0.5-_RADIUSBUCE) //_RADIUSBUCE是上图的r

然后将每次获取的模型uv坐标减去p坐标,相当于将坐标系平移p后获取的新的uv坐标,如上图绿色坐标系。

如下代码
i.RadiusBuceVU-float2(0.5-_RADIUSBUCE,0.5-_RADIUSBUCE)

然后我们就可以通过绿色坐标系进行计算是否在圆内了。

只要在新的坐标系中vu到原点的长度小于半径r就可以渲染颜色,否则就不渲染(cg函数为:discard--------跳出渲染管线不渲染)

if(length(i.RadiusBuceVU-float2(0.5-_RADIUSBUCE,0.5-_RADIUSBUCE))<_RADIUSBUCE)
{
col=tex2D(_MainTex,i.ModeUV);

}
else
{
discard;
}可以将上面的代码替换(绿色字体)测试一下
Shader "Custom/NewShader" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_RADIUSBUCE("_RADIUSBUCE",Range(0,0.5))=0.2
}
SubShader
{
pass
{

CGPROGRAM

#pragma exclude_renderers gles
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
float _RADIUSBUCE;
sampler2D _MainTex;


struct v2f
{
float4 pos : SV_POSITION ;
float2 ModeUV: TEXCOORD0;
float2 RadiusBuceVU : TEXCOORD1;
};
v2f vert(appdata_base v)
{
v2f o;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex); //v.vertex;
o.ModeUV=v.texcoord;
o.RadiusBuceVU=v.texcoord-float2(0.5,0.5);       //将模型UV坐标原点置为中心原点,为了方便计算


return o;
}




fixed4 frag(v2f i):COLOR
{
fixed4 col;
col=(0,1,1,0);


if(abs(i.RadiusBuceVU.x)<0.5-_RADIUSBUCE||abs(i.RadiusBuceVU.y)<0.5-_RADIUSBUCE)    //即上面说的|x|<(0.5-r)或|y|<(0.5-r)
{

col=tex2D(_MainTex,i.ModeUV);


}
else
{
if(length( i.RadiusBuceVU-float2(0.5-_RADIUSBUCE,0.5-_RADIUSBUCE)) <_RADIUSBUCE)
{
col=tex2D(_MainTex,i.ModeUV);

}
else
{
discard;
}
}
return col;  
}
ENDCG

}
}
 }

效果如下图

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_unity shader圆角矩形_15

发现现在已经完成了一个角的计算。其他角只要在获得的新uv坐标加个绝对值,将所有坐标转换到正坐标系下就可以了


最终代码如下

Shader "Custom/NewShader" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_RADIUSBUCE("_RADIUSBUCE",Range(0,0.5))=0.2
}
SubShader
{
pass
{

CGPROGRAM

#pragma exclude_renderers gles
#pragma vertex vert
#pragma fragment frag
#include "unitycg.cginc"
float _RADIUSBUCE;
sampler2D _MainTex;


struct v2f
{
float4 pos : SV_POSITION ;
float2 ModeUV: TEXCOORD0;
float2 RadiusBuceVU : TEXCOORD1;
};
v2f vert(appdata_base v)
{
v2f o;
o.pos=mul(UNITY_MATRIX_MVP,v.vertex); //v.vertex;
o.ModeUV=v.texcoord;
o.RadiusBuceVU=v.texcoord-float2(0.5,0.5);       //将模型UV坐标原点置为中心原点,为了方便计算


return o;
}




fixed4 frag(v2f i):COLOR
{
fixed4 col;
col=(0,1,1,0);


if(abs(i.RadiusBuceVU.x)<0.5-_RADIUSBUCE||abs(i.RadiusBuceVU.y)<0.5-_RADIUSBUCE)    //即上面说的|x|<(0.5-r)或|y|<(0.5-r)
{

col=tex2D(_MainTex,i.ModeUV);


}
else
 {
 if(length( abs( i.RadiusBuceVU)-float2(0.5-_RADIUSBUCE,0.5-_RADIUSBUCE)) <_RADIUSBUCE)
 {
 col=tex2D(_MainTex,i.ModeUV);

 }
 else
 {
 discard;
 } 
 }
return col;  
}
ENDCG

}
}
 }

最终效果

Unity 3D中的Image 实现圆角矩形效果 unity 画矩形_unity shader圆角矩形