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

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

詳細はこちら
Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

Q&A

1回答

9063閲覧

重なっても色の濃さが変わらない半透明Materialをつくりたい

_Beginner

総合スコア103

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

0グッド

1クリップ

投稿2019/10/14 02:12

編集2019/10/14 02:40

Unity 3D 2019

半透明のmaterial(Standard/Fade)を使って色のついた透明なオブジェクトを作っています。
しかし、重なった時その色が加算されてしまい、色が濃くなってしまいます。

そもそも透明なので重なって色が濃くなるのは当たり前なのですが...
重なってもその色のまま(RGBAを加算させない)ようにするにはどうすればいいのでしょうか?

探してみてもUnity標準のシェーダではなさそうなので、
おすすめのサイトがあれば教えてほしいです。

お願いします。

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

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

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

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

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

KanazawaKureha

2019/10/14 13:11

RGBAを加算しないとしても、乗算、減算、オーバーレイ、スクリーンなど方法は沢山ありますが、イメージはどういうシェーダなのですか?
guest

回答1

0

いくつか思いついた手を試してみましたが、いかがでしょうか?

対策なし

図1

案1:すでに描画済みのピクセルには描画しない
ステンシル機能を使い、単純に二度塗りを防いでみました。
半透明オブジェクトは奥から描画されていくため、奥のオブジェクトが最前面に出てきたように見えます。

ShaderLab

1Shader "Custom/SuppressingOverdraw" 2{ 3 Properties 4 { 5 _Color ("Color", Color) = (1,1,1,1) 6 _MainTex ("Albedo (RGB)", 2D) = "white" {} 7 _Glossiness ("Smoothness", Range(0,1)) = 0.5 8 _Metallic ("Metallic", Range(0,1)) = 0.0 9 } 10 SubShader 11 { 12 Tags { "Queue"="Transparent" "RenderType"="Transparent" } 13 14 Stencil { 15 Ref 1 16 Comp Greater 17 Pass Replace 18 } 19 20 CGPROGRAM 21 #pragma surface surf Standard fullforwardshadows alpha:fade 22 #pragma target 3.0 23 24 sampler2D _MainTex; 25 26 struct Input 27 { 28 float2 uv_MainTex; 29 }; 30 31 half _Glossiness; 32 half _Metallic; 33 fixed4 _Color; 34 35 void surf (Input IN, inout SurfaceOutputStandard o) 36 { 37 fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; 38 o.Albedo = c.rgb; 39 o.Metallic = _Metallic; 40 o.Smoothness = _Glossiness; 41 o.Alpha = c.a; 42 } 43 ENDCG 44 } 45 FallBack "Standard" 46}

図2

案2:塗りのみ二度塗り防止
2パス構成とし、第1パスでは単純な色塗りにして、このときステンシル機能を使い二度塗りを防ぎ、引き続きステンシルなしの完全透明状態で陰影を描画させてみました。
塗り方式が異なるため、見え方が変わって若干鮮やかに感じます。

ShaderLab

1Shader "Custom/SuppressingAlbedoOverdraw" 2{ 3 Properties 4 { 5 _Color ("Color", Color) = (1,1,1,1) 6 _MainTex ("Albedo (RGB)", 2D) = "white" {} 7 _Glossiness ("Smoothness", Range(0,1)) = 0.5 8 _Metallic ("Metallic", Range(0,1)) = 0.0 9 } 10 SubShader 11 { 12 Tags { "Queue"="Transparent" "RenderType"="Transparent" } 13 14 Pass 15 { 16 ZWrite Off 17 Blend SrcAlpha OneMinusSrcAlpha 18 19 Stencil { 20 Ref 1 21 Comp Greater 22 Pass Replace 23 } 24 25 CGPROGRAM 26 #pragma vertex vert 27 #pragma fragment frag 28 #pragma multi_compile_fog 29 30 #include "UnityCG.cginc" 31 32 struct appdata 33 { 34 float4 vertex : POSITION; 35 float2 uv : TEXCOORD0; 36 }; 37 38 struct v2f 39 { 40 float2 uv : TEXCOORD0; 41 UNITY_FOG_COORDS(1) 42 float4 vertex : SV_POSITION; 43 }; 44 45 sampler2D _MainTex; 46 float4 _MainTex_ST; 47 fixed4 _Color; 48 49 v2f vert (appdata v) 50 { 51 v2f o; 52 o.vertex = UnityObjectToClipPos(v.vertex); 53 o.uv = TRANSFORM_TEX(v.uv, _MainTex); 54 UNITY_TRANSFER_FOG(o,o.vertex); 55 return o; 56 } 57 58 fixed4 frag (v2f i) : SV_Target 59 { 60 fixed4 col = tex2D(_MainTex, i.uv) * _Color; 61 UNITY_APPLY_FOG(i.fogCoord, col); 62 return col; 63 } 64 ENDCG 65 } 66 67 CGPROGRAM 68 #pragma surface surf Standard fullforwardshadows alpha 69 #pragma target 3.0 70 71 sampler2D _MainTex; 72 73 struct Input 74 { 75 float2 uv_MainTex; 76 }; 77 78 half _Glossiness; 79 half _Metallic; 80 fixed4 _Color; 81 82 void surf (Input IN, inout SurfaceOutputStandard o) 83 { 84 fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; 85 o.Albedo = c.rgb; 86 o.Metallic = _Metallic; 87 o.Smoothness = _Glossiness; 88 o.Alpha = 0.0; 89 } 90 ENDCG 91 } 92 FallBack "Standard" 93}

図3

案3:完全透明で別途レンダリングし、2つの映像を混合する
前の2つの案と異なり、カメラにアタッチするスクリプトと合成用イメージエフェクトシェーダーで構成されています。
フェード対象にはレイヤーを設定(下記の例では「Faded」)し、マテリアルは完全不透明のものを使い、まず不透明状態でレンダリングします。
その後レイヤーを除外して完全透明で再度映像をレンダリングし、最後に2つを混ぜ合わせてみました。

ShaderLab

1Shader "Hidden/FaderEffect" 2{ 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 _Alpha ("Alpha", Range(0.0, 1.0)) = 0.5 7 } 8 SubShader 9 { 10 Blend SrcAlpha OneMinusSrcAlpha 11 Cull Off 12 ZWrite Off 13 ZTest Always 14 15 Pass 16 { 17 CGPROGRAM 18 #pragma vertex vert 19 #pragma fragment frag 20 21 #include "UnityCG.cginc" 22 23 struct appdata 24 { 25 float4 vertex : POSITION; 26 float2 uv : TEXCOORD0; 27 }; 28 29 struct v2f 30 { 31 float2 uv : TEXCOORD0; 32 float4 vertex : SV_POSITION; 33 }; 34 35 v2f vert (appdata v) 36 { 37 v2f o; 38 o.vertex = UnityObjectToClipPos(v.vertex); 39 o.uv = v.uv; 40 return o; 41 } 42 43 sampler2D _MainTex; 44 float _Alpha; 45 46 fixed4 frag (v2f i) : SV_Target 47 { 48 fixed4 col = tex2D(_MainTex, i.uv); 49 col.a *= _Alpha; 50 return col; 51 } 52 ENDCG 53 } 54 } 55}

C#

1using UnityEngine; 2 3[RequireComponent(typeof(Camera))] 4public class Fader : MonoBehaviour 5{ 6 [SerializeField] private string fadingLayer = "Faded"; 7 [SerializeField][Range(0.0f, 1.0f)] private float alpha = 0.5f; 8 [SerializeField] private Shader faderEffect; 9 10 private Camera subCamera; 11 private Material faderMaterial; 12 13 private void Awake() 14 { 15 // フェード対象レイヤーの番号を探し、見つからなければフェード処理を行わない 16 var fadingLayerIndex = LayerMask.NameToLayer(this.fadingLayer); 17 if (fadingLayerIndex < 0) 18 { 19 Destroy(this); 20 return; 21 } 22 23 // 完全透明撮影用のサブカメラを作成する 24 var mainCamera = this.GetComponent<Camera>(); 25 var subCameraObject = new GameObject("Sub Camera"); 26 this.subCamera = subCameraObject.AddComponent<Camera>(); 27 subCameraObject.transform.SetParent(this.transform, false); 28 this.subCamera.CopyFrom(mainCamera); 29 this.subCamera.enabled = false; 30 this.faderMaterial = new Material(this.faderEffect); 31 32 // レイヤーをレンダリング対象から除外する 33 var cullingMask = this.subCamera.cullingMask; 34 this.subCamera.cullingMask = cullingMask & ~(1 << fadingLayerIndex); 35 } 36 37 private void OnRenderImage(RenderTexture src, RenderTexture dest) 38 { 39 // まず完全不透明の映像を描画する 40 Graphics.Blit(src, dest); 41 42 // スクリーンと同サイズのレンダーテクスチャにレンダリング 43 var fadedImage = RenderTexture.GetTemporary(Screen.width, Screen.height); 44 var targetTexture = this.subCamera.targetTexture; 45 this.subCamera.targetTexture = fadedImage; 46 this.subCamera.Render(); 47 this.subCamera.targetTexture = targetTexture; 48 49 // 2つの映像を混合する 50 this.faderMaterial.SetFloat("_Alpha", 1.0f - this.alpha); 51 Graphics.Blit(fadedImage, dest, this.faderMaterial); 52 RenderTexture.ReleaseTemporary(fadedImage); 53 } 54}

図4

投稿2019/10/14 20:27

Bongo

総合スコア10811

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

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

moory

2021/06/22 12:55

丸一日、何度もあきらめかけながら、 このやり方を調べていたので、すごく助かりました! ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問