日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

解读Unity中的CG编写Shader系列4——unity中的圆角矩形shader

發布時間:2023/12/20 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 解读Unity中的CG编写Shader系列4——unity中的圆角矩形shader 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

http://blog.csdn.net/mobanchengshuang/article/details/38731035

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

這篇文章將利用這些知識實現一個簡單的,但是又很常用的例子:把一張圖片做成圓角矩形


例3:圓角矩形Shader

好吧我承認在做這個例子的時候走了不少彎路,由于本人對矩陣的知識掌握已經悉數還給老師,所以一開始用了一些笨辦法計算圓角矩形區域。

我們知道TEXTCOORD0是一個以對象為坐標系的坐標,并且范圍在該坐標的第一象限,取值為(0,0)到(1,1)

那么我們把每一張圖片都看做一張1X1大小的矩形

我們要在1X1大小的矩形中擦除4個角,應該是這樣:


以左上角為例,我們做一個輔助圓內切于這個角,半徑為0.1,那么我們將這個圓擦掉3/4,剩下的黃色弧線與這個角形成的區域就是我們要擦除的區域:


這個道理很簡單,那么我們對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型的屬性


最后代碼為:


[csharp]?view plaincopy print?
  • Shader?"Custom/RoundRect"?{??
  • ????Properties?{??
  • ????????//兩種內容模式,圖片模式??
  • ????????_MainTex?("Base?(RGB)",?2D)?=?"white"?{}??
  • ????????//純色模式??
  • ????????//_MainColor?("Color",?COLOR)?=?(1,1,1,1)??
  • ????????//圓角半徑,默認為0.1??
  • ????????_RoundRadius("Radius",float)?=?0.1??
  • ????}??
  • ????SubShader?{??
  • ??????????
  • ????????Pass{??
  • ????????????CGPROGRAM??
  • ?
  • ????????????#pragma?fragment?frag??
  • ?????????????
  • ????????????#include?"UnityCG.cginc"??
  • ????????????//獲取3個屬性?并傳值到CG代碼段??
  • ????????????sampler2D?_MainTex;??
  • ????????????float?_RoundRadius;??
  • ????????????float4?_MainColor;??
  • ??????????????
  • ????????????//片段著色器輸入結構體(可省略)??
  • ????????????struct?FragInput{??
  • ????????????????float2?texcoord:TEXCOORD0;??
  • ??????????????????
  • ????????????};??
  • ??
  • ????????????//片段著色器入口函數??
  • ????????????float4?frag(FragInput?input)?:?COLOR??
  • ????????????{??
  • ??????????????????
  • ??????????????????
  • ????????????????float4?c=tex2D(_MainTex,input.texcoord);//將圖片信息按坐標轉換成顏色??
  • ????????????????//float4?c=_MainColor;??//純色??
  • ??????????????????
  • ????????????????//x,y兩個變元,區間均為[0,1]??
  • ????????????????float?x=input.texcoord.x;??
  • ????????????????float?y=input.texcoord.y;??
  • ??????????????????
  • ????????????????//4條直線的常數部分??
  • ????????????????float?xt=1-_RoundRadius;??
  • ????????????????float?xb=_RoundRadius;??
  • ????????????????float?yl=_RoundRadius;??
  • ????????????????float?yr=1-_RoundRadius;??
  • ????????????????//如果(x,y)不在4條直線構成的矩形中(上圖的白色區域)??
  • ????????????????if(!(x<xt&&x>xb&&y>yl&&y<yr))??
  • ????????????????{??
  • ??????????????????
  • ????????????????????//如果(x.y)不在上圖的綠色區域??
  • ????????????????????if(!((x<xt&&x>xb)?||?(y>yl&&y<yr)?))??
  • ????????????????????????//數學不好,好像判斷的復雜了,如果您可以直接寫出紫色區域??
  • ????????????????????????//的不等式組那么可以簡單點??
  • ????????????????{??
  • ????????????????//計算四個頂點的坐標??
  • ????????????????float2?plb=float2(_RoundRadius,_RoundRadius);??
  • ????????????????float2?plt=float2(_RoundRadius,1-_RoundRadius);??
  • ????????????????float2?prt=float2(1-_RoundRadius,1-_RoundRadius);??
  • ????????????????float2?prb=float2(1-_RoundRadius,_RoundRadius);??
  • ??????????????
  • ????????????????//計算x,y分別到4個頂點的距離??
  • ????????????????float?distlb=sqrt(pow((x-plb.x),2)+pow((y-plb.y),2));??
  • ????????????????float?distlt=sqrt(pow((x-plt.x),2)+pow((y-plt.y),2));??
  • ????????????????float?distrt=sqrt(pow((x-prt.x),2)+pow((y-prt.y),2));??
  • ????????????????float?distrb=sqrt(pow((x-prb.x),2)+pow((y-prb.y),2));??
  • ??????????????????
  • ????????????????//對4個距離取最小值??
  • ????????????????float?dist=min(distlb,distlt);??
  • ????????????????dist=min(dist,distrt);??
  • ????????????????dist=min(dist,distrb);??
  • ??????????????????
  • ????????????????//將大于半徑的表面剔除??
  • ????????????????if(dist>_RoundRadius)??
  • ????????????????????????discard;??
  • ??
  • ????????????????}??
  • ??????????????????
  • ??????????????????
  • ????????????????}??
  • ??
  • ????????????????return?c;??
  • ??
  • ????????????}??
  • ????????????ENDCG??
  • ????????}??
  • ??
  • ??????????
  • ????}???
  • ????FallBack?"Diffuse"??
  • }??

  • 最后運行的效果,不同Radius不同尺寸的圖片進行圓角矩形剔除


    當radius設為0.25時我們可以得到一個圓,所以我們的RoundRadius屬性可以設置為一個0.01~0.25的rang


    由于我是windows系統,mac os下好像有點問題,不知道是不是省略了頂點著色器的問題,發現原因后再來補正

    總結

    以上是生活随笔為你收集整理的解读Unity中的CG编写Shader系列4——unity中的圆角矩形shader的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。