🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

7379閲覧

【Unity】uGUIで枠線付き角丸のボタンを作りたい

nakamu

総合スコア82

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

1クリップ

投稿2019/12/20 08:39

イメージ説明

枠線付きの透過した状態まで作って最後下記のリンクを参考にを角丸にしようとしましたが
角丸シェーダー

結果は案の定画像のような状態です。
角丸シェーダを追加した結果

別の角丸シェーダを使うべきでしょうか?

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

まず透明度が反映されない件については、frag末尾のreturn col;の手前でcol.a = alpha;という風に元の画像のアルファを無視して新しいアルファで上書きしていることによるかと思います。ここをcol.a *= alpha;に変更して、元のアルファと角丸アルファの積を最終的なアルファとして出力させればいいんじゃないでしょうか。
ご質問者さんのボタン画像をまねて下記のような画像を作り...

図1

修正を加えたシェーダーで、Radius pxを1~92に変化させたところ下図のようになりました。

図2

もし内側の境界も丸めたいとなると、テクスチャのサンプリング位置をずらしてむりやり丸くひずめてやることになりそうです。
RoundedRect.shaderを複製し、さしあたり名前は「RoundedRectWarp.shader」として、内容は下記のように変更したところ...

ShaderLab

1Shader "Custom/2D/RoundedRectWarp" { 2Properties { 3 _MainTex ("Texture", 2D) = "white" {} 4 _Radius ("Radius px", Float) = 10 5 _Width ("Width px", Float) = 100 6 _Height ("Height px", Float) = 100 7 8 // おまけ...ソフトエッジを使うかどうかをトグルで切り替えるようにする 9 [Toggle(SOFT_EDGE)] _SoftEdge("Soft edge", Float) = 0 10 11 // required for UI.Mask 12 [HideInInspector] _StencilComp ("Stencil Comparison", Float) = 8 13 [HideInInspector] _Stencil ("Stencil ID", Float) = 0 14 [HideInInspector] _StencilOp ("Stencil Operation", Float) = 0 15 [HideInInspector] _StencilWriteMask ("Stencil Write Mask", Float) = 255 16 [HideInInspector] _StencilReadMask ("Stencil Read Mask", Float) = 255 17 [HideInInspector] _ColorMask ("Color Mask", Float) = 15 18} 19SubShader { 20 Tags { 21 "RenderType"="Transparent" 22 "Queue"="Transparent" 23 } 24 25 // required for UI.Mask 26 Stencil 27 { 28 Ref [_Stencil] 29 Comp [_StencilComp] 30 Pass [_StencilOp] 31 ReadMask [_StencilReadMask] 32 WriteMask [_StencilWriteMask] 33 } 34 35 Cull Off 36 Lighting Off 37 ZTest [unity_GUIZTestMode] 38 39 // Alpha blending. 40 ZWrite Off 41 Blend SrcAlpha OneMinusSrcAlpha 42 43 Pass { 44 CGPROGRAM 45 #pragma vertex vert 46 #pragma fragment frag 47 48 // SOFT_EDGEなし・ありでマルチコンパイル 49 #pragma multi_compile _ SOFT_EDGE 50 51 #include "UnityCG.cginc" 52 53 struct appdata { 54 float4 vertex : POSITION; 55 float2 uv : TEXCOORD0; 56 float4 color : COLOR; 57 }; 58 59 struct v2f { 60 float2 uv : TEXCOORD0; 61 float4 vertex : SV_POSITION; 62 float4 color : COLOR; 63 }; 64 65 sampler2D _MainTex; 66 float4 _MainTex_ST; 67 float _Radius; 68 float _Width; 69 float _Height; 70 71 v2f vert (appdata v) { 72 v2f o; 73 o.vertex = UnityObjectToClipPos(v.vertex); 74 o.uv = TRANSFORM_TEX(v.uv, _MainTex); 75 o.color = v.color; 76 return o; 77 } 78 79 float MakeEdge(float from, float to, fixed t) { 80 fixed r = max(_Radius, 2); 81 t = saturate(t * (r - t)); 82 return lerp(from, to, t); 83 } 84 85 86 float2 GetRadiusToPointVector(float2 pixel, float2 halfRes, float radius) { 87 float2 firstQuadrant = abs(pixel); 88 float2 radiusToPoint = firstQuadrant - (halfRes - radius); 89 radiusToPoint = max(radiusToPoint, 0.0); 90 return radiusToPoint; 91 } 92 93 float SoftRounded(float2 pixel, float2 halfRes, float radius) { 94 float2 v = GetRadiusToPointVector(pixel, halfRes, radius); 95 float alpha = 1.0 - length(v) / radius; 96 alpha = MakeEdge(0, 1, alpha); 97 return alpha; 98 } 99 100 float HardRounded(float2 pixel, float2 halfRes, float radius) { 101 float2 v = GetRadiusToPointVector(pixel, halfRes, radius); 102 float alpha = 1.0 - floor(length(v) / radius); 103 return alpha; 104 } 105 106 fixed4 frag (v2f i) : SV_Target { 107 float2 uvInPixel = (i.uv - 0.5) * float2(_Width, _Height); 108 float2 halfRes = float2(_Width, _Height) * 0.5; 109 110 // SOFT_EDGEの有無によって関数を切り替える 111 #ifdef SOFT_EDGE 112 float alpha = SoftRounded(uvInPixel, halfRes, _Radius); 113 #else 114 float alpha = HardRounded(uvInPixel, halfRes, _Radius); 115 #endif 116 117 // まず角の丸め部分の中心を基準とした座標を得て... 118 float2 v = GetRadiusToPointVector(uvInPixel, halfRes, _Radius); 119 120 // 丸め部分は45°の直線に対して対称なので、話を簡単にするためその直線で折り返して... 121 float2 foldedV = float2(max(v.x, v.y), min(v.x, v.y)); 122 123 // 丸め領域内であるならば... 124 if (foldedV.y > 0.0) { 125 // 丸め部分中心と注目ピクセルを結ぶ線分を最外周まで延長し 126 // その衝突点と丸め部分中心との距離を求め... 127 float l = length(float2(_Radius, foldedV.y * _Radius / foldedV.x)); 128 129 // 半径に対するその距離の割合だけテクスチャサンプリング位置をずらす 130 float2 newUvInPixel = uvInPixel + ((l / _Radius) - 1.0) * sign(uvInPixel) * v; 131 i.uv = (newUvInPixel / float2(_Width, _Height)) + 0.5; 132 } 133 134 fixed4 col = tex2D(_MainTex, i.uv) * i.color; 135 136 // col.aは上書きでなく乗算代入とし、元画像のアルファも反映させる 137 col.a *= alpha; 138 139 return col; 140 } 141 ENDCG 142 } 143} 144}

これを使ったマテリアルに変えて、Radius pxを1~92に変化させたところ下図のようになりました。

図3

投稿2019/12/20 22:54

Bongo

総合スコア10811

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

nakamu

2019/12/21 03:57

シェーダーに関してまだまだ疎く、大変助かりました! RoundedRectWarp.shaderが望んでたものです。ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問