質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.50%
Unity

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

Q&A

解決済

2回答

3353閲覧

Unity2Dでスプライトマスクにグラデーションをかける方法

yrema

総合スコア286

Unity

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

0グッド

1クリップ

投稿2019/03/02 03:08

編集2019/03/02 20:52

やりたいことは下記のように2つの画像にアルファ値が段階的に変わっていくマスクをかけて重ねたいです。
イメージ説明

ところが、Sprite Maskを使うとアルファが100以外のものはアルファ0とみなされてしまうようです。
これを実現する方法はないでしょうか?

また、目的は「タイルとして作ったスプライトのつなぎ目をなだらかに見せたい」なので、
上記質問の方法に限らず、その目的を達成できる方法があれば教えていただきたいです。

◆追記
やりたいこと補足画像
イメージ説明

◆環境
Unity2017 3.1f1

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

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

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

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

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

guest

回答2

0

ベストアンサー

Sprite Maskでは半透明のマスク掛けは無理かもしれません。UIに関する話題ですが、Unity2D - 【Unity 2D】マテリアルをMaskにすることは出来ないのでしょうか|teratailでもご参考として挙げさせていただいたUnity uGUIで綺麗なマスク表現 - 渋谷ほととぎす通信のように、半透明抜きしたい側のマテリアルに半透明化機能を持たせることになるんじゃないかと思います。

一例として、ダウンロードアーカイブから入手できるビルトインシェーダーのSprites-Default.shaderをプロジェクトにコピーし、下記のように改造して...

ShaderLab

1// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 3Shader "Sprites/Gradient Alpha" 4{ 5 Properties 6 { 7 [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} 8 _Color ("Tint", Color) = (1,1,1,1) 9 [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 10 [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1) 11 [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1) 12 [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {} 13 [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0 14 15 // マテリアルにグラデーション用プロパティを追加 16 [Space] 17 [Header(Gradient)] 18 _GradientAlpha1 ("Alpha 1", Range(0, 1)) = 0 19 _GradientAlpha2 ("Alpha 2", Range(0, 1)) = 1 20 _GradientScale ("Scale", Range(0, 2)) = 1 21 _GradientAngle ("Angle", Range(0, 360)) = 0 22 _GradientOffset ("Offset", Range(-1, 1)) = 0 23 } 24 25 SubShader 26 { 27 Tags 28 { 29 "Queue"="Transparent" 30 "IgnoreProjector"="True" 31 "RenderType"="Transparent" 32 "PreviewType"="Plane" 33 "CanUseSpriteAtlas"="True" 34 } 35 36 Cull Off 37 Lighting Off 38 ZWrite Off 39 Blend One OneMinusSrcAlpha 40 41 Pass 42 { 43 CGPROGRAM 44 // バーテックスシェーダー、フラグメントシェーダーを独自仕様に差し替え 45 #pragma vertex vert 46 #pragma fragment frag 47 48 #pragma target 2.0 49 #pragma multi_compile_instancing 50 #pragma multi_compile _ PIXELSNAP_ON 51 #pragma multi_compile _ ETC1_EXTERNAL_ALPHA 52 #include "UnitySprites.cginc" 53 54 // 追加したプロパティのための変数を追加 55 float _GradientAlpha1; 56 float _GradientAlpha2; 57 float _GradientScale; 58 float _GradientAngle; 59 float _GradientOffset; 60 61 // v2fもカスタマイズする 62 struct v2fCustom 63 { 64 float4 vertex : SV_POSITION; 65 fixed4 color : COLOR; 66 float2 texcoord : TEXCOORD0; 67 float alpha : TEXCOORD1; // グラデーション描画のためのアルファ情報を追加 68 UNITY_VERTEX_OUTPUT_STEREO 69 }; 70 71 v2fCustom vert(appdata_t IN) 72 { 73 v2fCustom OUT; 74 75 UNITY_SETUP_INSTANCE_ID (IN); 76 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); 77 78 OUT.vertex = UnityFlipSprite(IN.vertex, _Flip); 79 OUT.vertex = UnityObjectToClipPos(OUT.vertex); 80 OUT.texcoord = IN.texcoord; 81 OUT.color = IN.color * _Color * _RendererColor; 82 83 // グラデーションの角度に合わせてスプライト頂点を回転、オフセット分だけ移動、 84 // スケールで割った際のX座標を求め、さらに範囲を-1~1 → 0~1に変える 85 float theta = _GradientAngle * UNITY_PI / 180; 86 OUT.alpha = ((dot(float2(cos(theta), -sin(theta)), IN.vertex.xy) + _GradientOffset * 2) / _GradientScale) + 0.5; 87 88 #ifdef PIXELSNAP_ON 89 OUT.vertex = UnityPixelSnap (OUT.vertex); 90 #endif 91 92 return OUT; 93 } 94 95 fixed4 frag(v2fCustom IN) : SV_Target 96 { 97 fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color; 98 99 // プロパティから設定したアルファ1とアルファ2をバーテックスシェーダーで求めた比率で 100 // 混合し、0~1におさめてアルファに乗算する 101 c.a *= saturate(lerp(_GradientAlpha1, _GradientAlpha2, IN.alpha)); 102 103 c.rgb *= c.a; 104 105 return c; 106 } 107 ENDCG 108 } 109 } 110} 111

黄緑芝生の手前に緑芝生を配置し、緑芝生のマテリアルをその「Sprites/Gradient Alpha」を使ったものに差し替えたところ、下図のようになりました。

結果

#追記
不透明にしたいエッジを選択する方式を検討してみました。同じくSprites-Default.shaderをベースに下記のように改造し...

ShaderLab

1// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 3Shader "Sprites/Edge Gradient Alpha" 4{ 5 Properties 6 { 7 [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} 8 _Color ("Tint", Color) = (1,1,1,1) 9 [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 10 [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1) 11 [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1) 12 [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {} 13 [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0 14 15 [Space] 16 [Header(Gradient)] 17 _GradientAlpha1 ("Alpha 1", Range(0, 1)) = 0 18 _GradientAlpha2 ("Alpha 2", Range(0, 1)) = 1 19 [PowerSlider(2.0)] _GradientExponent ("Exponent", Range(0.125, 8)) = 2 20 [Toggle] _GradientEdgeTop ("Top", Float) = 0 21 [Toggle] _GradientEdgeBottom ("Bottom", Float) = 0 22 [Toggle] _GradientEdgeLeft ("Left", Float) = 0 23 [Toggle] _GradientEdgeRight ("Right", Float) = 0 24 } 25 26 SubShader 27 { 28 Tags 29 { 30 "Queue"="Transparent" 31 "IgnoreProjector"="True" 32 "RenderType"="Transparent" 33 "PreviewType"="Plane" 34 "CanUseSpriteAtlas"="True" 35 } 36 37 Cull Off 38 Lighting Off 39 ZWrite Off 40 Blend One OneMinusSrcAlpha 41 42 Pass 43 { 44 CGPROGRAM 45 #pragma vertex vert 46 #pragma fragment frag 47 #pragma target 2.0 48 #pragma multi_compile_instancing 49 #pragma multi_compile _ PIXELSNAP_ON 50 #pragma multi_compile _ ETC1_EXTERNAL_ALPHA 51 #include "UnitySprites.cginc" 52 53 float _GradientAlpha1; 54 float _GradientAlpha2; 55 float _GradientExponent; 56 float _GradientEdgeTop; 57 float _GradientEdgeBottom; 58 float _GradientEdgeLeft; 59 float _GradientEdgeRight; 60 61 struct v2fCustom 62 { 63 float4 vertex : SV_POSITION; 64 fixed4 color : COLOR; 65 float2 texcoord : TEXCOORD0; 66 float2 position : TEXCOORD1; // グラデーション用の位置 67 UNITY_VERTEX_OUTPUT_STEREO 68 }; 69 70 v2fCustom vert(appdata_t IN) 71 { 72 v2fCustom OUT; 73 74 UNITY_SETUP_INSTANCE_ID (IN); 75 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); 76 77 OUT.vertex = UnityFlipSprite(IN.vertex, _Flip); 78 OUT.vertex = UnityObjectToClipPos(OUT.vertex); 79 OUT.texcoord = IN.texcoord; 80 OUT.color = IN.color * _Color * _RendererColor; 81 OUT.position = IN.vertex.xy * 2; 82 83 #ifdef PIXELSNAP_ON 84 OUT.vertex = UnityPixelSnap (OUT.vertex); 85 #endif 86 87 return OUT; 88 } 89 90 fixed4 frag(v2fCustom IN) : SV_Target 91 { 92 fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color; 93 94 float alpha = saturate(dot(float4( 95 pow(saturate(_GradientEdgeTop * IN.position.y), _GradientExponent), 96 pow(saturate(_GradientEdgeBottom * -IN.position.y), _GradientExponent), 97 pow(saturate(_GradientEdgeLeft * -IN.position.x), _GradientExponent), 98 pow(saturate(_GradientEdgeRight * IN.position.x), _GradientExponent)), 1)); 99 c.a *= saturate(lerp(_GradientAlpha1, _GradientAlpha2, alpha)); 100 101 c.rgb *= c.a; 102 103 return c; 104 } 105 ENDCG 106 } 107 } 108}

インスペクタ上で各チェックボックスを切り替えると、その方向のエッジ表示が切り替わります。

結果

投稿2019/03/02 12:29

編集2019/03/02 22:33
Bongo

総合スコア10807

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

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

yrema

2019/03/02 16:59

なるほど、これは素晴らしいですね。質問なのですが、このグラディエーションは1方向のみにしかできないのでしょうか?例えば、中央から離れにつれて円形状にアルファ値が下がるようなことが可能かどうかということです。
yrema

2019/03/02 20:54

◆追記に補足画像を追加しました。アルファ値の変化を一方向ではなく変化させたいです。
Bongo

2019/03/02 22:41 編集

ある点からの距離によってアルファを決定すれば円形のグラデーションが作れそうですが、それよりも周りのスプライトとのつなぎ目をなめらかにする目的に特化したアルファ決定方式にした方が、使い勝手がよさそうな気がしてきました。 一案として、上下左右のエッジごとにチェックボックスを設ける方式を考えてみましたので追記します。
yrema

2019/03/02 22:55

凄まじいですね。本当にありがとうございます!
yrema

2019/03/02 23:49

77行目のUnityFlipSpriteが未定義というエラーが出ましたが、これはどこで定義されてますか?
Bongo

2019/03/03 00:35

UnityFlipSpriteはUnitySprites.cgincに入っているはずですが、なぜでしょうかね...? もし未定義エラーが消えないようでしたら、 OUT.vertex = UnityFlipSprite(IN.vertex, _Flip); の部分を... OUT.vertex = float4(IN.vertex.xy * _Flip, IN.vertex.z, 1.0); に変えてみてください。 それと後で気付いたのですが、4方向のエッジのオン・オフだけでは斜めに隣り合ったタイルとのつながりに対応できないですね... 4隅とのブレンド機能を追加してみましたので、斜めの隣接がある場合はこちらも試してみてください。
guest

0

#追記
4隅のチェックボックスを追加しました。字数制限に達してしまったので、すみませんが別回答として追記しました。

ShaderLab

1// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 3Shader "Sprites/Edge Gradient Alpha" 4{ 5 Properties 6 { 7 [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} 8 _Color ("Tint", Color) = (1,1,1,1) 9 [MaterialToggle] PixelSnap ("Pixel snap", Float) = 0 10 [HideInInspector] _RendererColor ("RendererColor", Color) = (1,1,1,1) 11 [HideInInspector] _Flip ("Flip", Vector) = (1,1,1,1) 12 [PerRendererData] _AlphaTex ("External Alpha", 2D) = "white" {} 13 [PerRendererData] _EnableExternalAlpha ("Enable External Alpha", Float) = 0 14 15 [Space] 16 [Header(Gradient)] 17 _GradientAlpha1 ("Alpha 1", Range(0, 1)) = 0 18 _GradientAlpha2 ("Alpha 2", Range(0, 1)) = 1 19 [PowerSlider(2.0)] _GradientExponent ("Exponent", Range(0.125, 8)) = 2 20 [Header(Edges)] 21 [Toggle] _GradientEdgeTop ("Top", Float) = 0 22 [Toggle] _GradientEdgeBottom ("Bottom", Float) = 0 23 [Toggle] _GradientEdgeLeft ("Left", Float) = 0 24 [Toggle] _GradientEdgeRight ("Right", Float) = 0 25 [Header(Corners)] 26 [Toggle] _GradientCornerTopLeft ("Top Left", Float) = 0 27 [Toggle] _GradientCornerBottomLeft ("Bottom Left", Float) = 0 28 [Toggle] _GradientCornerTopRight ("Top Right", Float) = 0 29 [Toggle] _GradientCornerBottomRight ("Bottom Right", Float) = 0 30 } 31 32 SubShader 33 { 34 Tags 35 { 36 "Queue"="Transparent" 37 "IgnoreProjector"="True" 38 "RenderType"="Transparent" 39 "PreviewType"="Plane" 40 "CanUseSpriteAtlas"="True" 41 } 42 43 Cull Off 44 Lighting Off 45 ZWrite Off 46 Blend One OneMinusSrcAlpha 47 48 Pass 49 { 50 CGPROGRAM 51 #pragma vertex vert 52 #pragma fragment frag 53 #pragma target 2.0 54 #pragma multi_compile_instancing 55 #pragma multi_compile _ PIXELSNAP_ON 56 #pragma multi_compile _ ETC1_EXTERNAL_ALPHA 57 #include "UnitySprites.cginc" 58 59 float _GradientAlpha1; 60 float _GradientAlpha2; 61 float _GradientExponent; 62 float _GradientEdgeTop; 63 float _GradientEdgeBottom; 64 float _GradientEdgeLeft; 65 float _GradientEdgeRight; 66 float _GradientCornerTopLeft; 67 float _GradientCornerBottomLeft; 68 float _GradientCornerTopRight; 69 float _GradientCornerBottomRight; 70 71 struct v2fCustom 72 { 73 float4 vertex : SV_POSITION; 74 fixed4 color : COLOR; 75 float2 texcoord : TEXCOORD0; 76 float2 position : TEXCOORD1; // グラデーション用の位置 77 UNITY_VERTEX_OUTPUT_STEREO 78 }; 79 80 v2fCustom vert(appdata_t IN) 81 { 82 v2fCustom OUT; 83 84 UNITY_SETUP_INSTANCE_ID (IN); 85 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); 86 87 OUT.vertex = UnityFlipSprite(IN.vertex, _Flip); 88 OUT.vertex = UnityObjectToClipPos(OUT.vertex); 89 OUT.texcoord = IN.texcoord; 90 OUT.color = IN.color * _Color * _RendererColor; 91 OUT.position = IN.vertex.xy * 2; 92 93 #ifdef PIXELSNAP_ON 94 OUT.vertex = UnityPixelSnap (OUT.vertex); 95 #endif 96 97 return OUT; 98 } 99 100 fixed4 frag(v2fCustom IN) : SV_Target 101 { 102 fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color; 103 104 float4 edgeFactor = float4(_GradientEdgeTop, _GradientEdgeBottom, _GradientEdgeLeft, _GradientEdgeRight); 105 float4 cornerFactor = float4(_GradientCornerTopLeft, _GradientCornerTopRight, _GradientCornerBottomLeft, _GradientCornerBottomRight); 106 float4 edge = pow(saturate(IN.position.yyxx * float4(1, -1, -1, 1)), _GradientExponent); 107 float4 corner = edge.xxyy * edge.zwzw * cornerFactor; 108 float alpha = saturate(max(max(max(max(dot(edge, edgeFactor), corner.x), corner.y), corner.z), corner.w)); 109 c.a *= saturate(lerp(_GradientAlpha1, _GradientAlpha2, alpha)); 110 111 c.rgb *= c.a; 112 113 return c; 114 } 115 ENDCG 116 } 117 } 118}

イメージ説明

投稿2019/03/03 00:34

Bongo

総合スコア10807

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問