先上個效果圖
制作思路
如上圖我們要渲染的就是上圖帶顏色的部分
步驟:
先獲取黃色和藍綠部分
例如以下圖
算法
|U|<(0.5-r)或|V|<(0.5-r)
注意的是模型貼圖最大值是1.
然后獲取紅色的四份之中的一個圓部分
實現過程
首先在unity里創建一個shader。
創建完畢后
然后雙擊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拖到物體上面去。
效果例如以下圖:
好了如今我們來切圓角矩形。
要說明的是我們為了計算方便坐標系原點在uv的中心,可是unity模型的uv的原點在左下角例如以下圖,切vu取值范圍(0,1)。就是說貼圖的像素坐標也是(0,1)表示全部的像素坐標點
unity的uv坐標系
所以為了統一,我們將unity的uv坐標系處理成中心坐標系,用一個變量存儲處理后的坐標系
方法是
unity的uv-float(0.5,0.5)
首先我們實現下圖區域的顯示
改動上面的代碼,我們須要加入一個圓角半徑的屬性。然后我們要獲取上面所說的黃色和藍綠色部分,加入代碼以下紅色字體。
代碼改動后例如以下:
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
}
}
}
效果例如以下圖:
好了如今我們開始獲取紅色四份之中的一個圓區域
繼續改動代碼(藍色字體)
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就是非下圖區域的其它區域
if推斷的區域
else區域(藍色框的區域)
然后我們在else下再推斷像素點是否在四份之中的一個圓呢即可了
if(length( abs( i.RadiusBuceVU)-float2(0.5-_RADIUSBUCE,0.5-_RADIUSBUCE)) <_RADIUSBUCE)
上面這句推斷有點亂
首先我們先獲取UV坐標u和v都是正半軸的四份之中的一個圓:以下藍色框區域。
首先我們獲取下圖p點坐標
即: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
}
}
}
效果例如以下圖
發現如今已經完畢了一個角的計算。其它角僅僅要在獲得的新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
}
}
}
終於效果
項目下載鏈接
http://download.csdn.net/detail/fengya1/9449577