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

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

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

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

HLSL

HLSLは、米マイクロソフト社によって開発された Direct3D APIで使われるプロプライエタリなシェーディング言語です。

Q&A

解決済

1回答

8932閲覧

Unityのシェーダーでアルファ値=0にしたはずが半透明になってしまう

yrema

総合スコア287

Unity

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

HLSL

HLSLは、米マイクロソフト社によって開発された Direct3D APIで使われるプロプライエタリなシェーディング言語です。

0グッド

0クリップ

投稿2021/01/20 04:00

シェーダーを勉強中です。
タイトルの通りですが、下記コードの★の部分でalpha = 0としているのですが、
期待では全透明になるはずが半透明になってしまいます。なぜでしょうか?

HLSL

1// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 3Shader "Sprites/TestShader" 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 17 } 18 19 SubShader 20 { 21 Tags 22 { 23 "Queue"="Transparent" 24 "IgnoreProjector"="True" 25 "RenderType"="Transparent" 26 "PreviewType"="Plane" 27 "CanUseSpriteAtlas"="True" 28 } 29 30 Cull Off 31 Lighting Off 32 ZWrite Off 33 Blend One OneMinusSrcAlpha 34 35 Pass 36 { 37 CGPROGRAM 38 #pragma vertex vert 39 #pragma fragment frag 40 #pragma target 2.0 41 #pragma multi_compile_instancing 42 #pragma multi_compile _ PIXELSNAP_ON 43 #pragma multi_compile _ ETC1_EXTERNAL_ALPHA 44 #include "UnitySprites.cginc" 45 46 struct v2fCustom 47 { 48 float4 vertex : SV_POSITION; 49 fixed4 color : COLOR; 50 float2 texcoord : TEXCOORD0; 51 float2 position : TEXCOORD1; 52 UNITY_VERTEX_OUTPUT_STEREO 53 }; 54 55 v2fCustom vert(appdata_t IN) 56 { 57 v2fCustom OUT; 58 59 UNITY_SETUP_INSTANCE_ID (IN); 60 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); 61 62 OUT.vertex = UnityFlipSprite(IN.vertex, _Flip); 63 OUT.vertex = UnityObjectToClipPos(OUT.vertex); 64 OUT.texcoord = IN.texcoord; 65 OUT.color = IN.color * _Color * _RendererColor; 66 OUT.position = IN.vertex.xy * 2; 67 68 #ifdef PIXELSNAP_ON 69 OUT.vertex = UnityPixelSnap (OUT.vertex); 70 #endif 71 72 return OUT; 73 } 74 75 fixed4 frag(v2fCustom IN) : SV_Target 76 { 77 fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color; 78 79 float alpha = 0; // ★ 0にすると全透明になると期待するが半透明になってしまう 80 c.a = alpha; 81 82 return c; 83 } 84 ENDCG 85 } 86 } 87}

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

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

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

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

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

guest

回答1

0

ベストアンサー

ブレンドモードがBlend One OneMinusSrcAlphaとなっていますので、描画結果はシェーダーが出力した色 + 下地の色 × (1.0 - シェーダーが出力した色のアルファ)となるはずです。アルファが0のときの描画結果はシェーダーが出力した色 + 下地の色となり、加算合成をしているのと同じになるわけですね。

アルファが0のときに完全透明にしたいとなると、ブレンドモードをBlend SrcAlpha OneMinusSrcAlphaにするのがいいかと思います。ですがそれだと普通のアルファブレンディングと同じになってしまうはずですが、ご質問者さんの意図する挙動はどのようなものでしょうか。
「アルファ1だと完全不透明、アルファを下げていくとだんだん加算合成のようになっていき、さらにアルファを下げていくと絵が薄くなり、アルファ0で完全透明」みたいな感じでしょうか?

##マテリアル案

一案として下記のようなものはいかがでしょうか?

ShaderLab

1// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) 2 3Shader "Sprites/TestShader" 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 _Alpha ("Alpha", Range(0, 1)) = 1 15 _Exponent ("Exponent", Range(1, 16)) = 1 16 } 17 18 SubShader 19 { 20 Tags 21 { 22 "Queue"="Transparent" 23 "IgnoreProjector"="True" 24 "RenderType"="Transparent" 25 "PreviewType"="Plane" 26 "CanUseSpriteAtlas"="True" 27 } 28 29 Cull Off 30 Lighting Off 31 ZWrite Off 32 Blend One OneMinusSrcAlpha 33 34 Pass 35 { 36 CGPROGRAM 37 #pragma vertex vert 38 #pragma fragment frag 39 #pragma target 2.0 40 #pragma multi_compile_instancing 41 #pragma multi_compile _ PIXELSNAP_ON 42 #pragma multi_compile _ ETC1_EXTERNAL_ALPHA 43 #include "UnitySprites.cginc" 44 45 struct v2fCustom 46 { 47 float4 vertex : SV_POSITION; 48 fixed4 color : COLOR; 49 float2 texcoord : TEXCOORD0; 50 float2 position : TEXCOORD1; 51 UNITY_VERTEX_OUTPUT_STEREO 52 }; 53 54 v2fCustom vert(appdata_t IN) 55 { 56 v2fCustom OUT; 57 58 UNITY_SETUP_INSTANCE_ID (IN); 59 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); 60 61 OUT.vertex = UnityFlipSprite(IN.vertex, _Flip); 62 OUT.vertex = UnityObjectToClipPos(OUT.vertex); 63 OUT.texcoord = IN.texcoord; 64 OUT.color = IN.color * _Color * _RendererColor; 65 OUT.position = IN.vertex.xy * 2; 66 67 #ifdef PIXELSNAP_ON 68 OUT.vertex = UnityPixelSnap (OUT.vertex); 69 #endif 70 71 return OUT; 72 } 73 74 float _Alpha; 75 float _Exponent; 76 77 fixed4 frag(v2fCustom IN) : SV_Target 78 { 79 fixed4 c = SampleSpriteTexture (IN.texcoord) * IN.color; 80 81 // アルファ変化時の見た目の変化を実演するため、アルファを 82 // プロパティにして外部から操作できるようにした 83 float alpha = _Alpha; 84 c.a = alpha; 85 86 // 通常のアルファブレンディングではRGBにアルファがそのまま乗算されるが、 87 // ここで「白黒反転して冪乗して白黒反転」の操作を加えることで 88 // 乗算値の変化が非線形なカーブとなって、中間のアルファのときに 89 // 乗算値が通常よりも高くなり、加算合成に近づく 90 c.rgb *= 1.0 - pow(1.0 - c.a, _Exponent); 91 92 return c; 93 } 94 ENDCG 95 } 96 } 97}

ブレンドモードはBlend One OneMinusSrcAlphaとしておき、RGBへのアルファ乗算はfrag内で行うようにしてみました。
Exponentが1のとき...つまり通常のアルファブレンディングだと下図のようになりますが(さまざまなアルファ値のときにどう見えるかをご覧に入れようと思ってGIFにしたのですが、代償として階調数が落ちてしまいました)...

図1

Exponentを8に上げると、半透明のときにRGBに乗算される値が実際のアルファよりも高めに引き上げられ、加算合成に近い結果になります。ですがアルファが0になると乗算値も0まで落ち込むので、アルファが0のときには完全透明になるというわけです。

図2

投稿2021/01/20 21:30

編集2021/01/21 03:47
Bongo

総合スコア10811

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

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

yrema

2021/01/20 23:11

ご回答ありがとうございます。 >「アルファ1だと完全不透明、アルファを下げていくとだんだん加算合成のようになっていき、さらにアルファを下げていくと絵が薄くなり、アルファ0で完全透明」 おっしゃる通りです。
Bongo

2021/01/21 03:48

マテリアル案を考えてみましましたが、いかがでしょうか?
yrema

2021/01/21 04:00

ありがとうございます!期待通りの動きです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問