Unity 3D 2019
半透明のmaterial(Standard/Fade)を使って色のついた透明なオブジェクトを作っています。
しかし、重なった時その色が加算されてしまい、色が濃くなってしまいます。
そもそも透明なので重なって色が濃くなるのは当たり前なのですが...
重なってもその色のまま(RGBAを加算させない)ようにするにはどうすればいいのでしょうか?
探してみてもUnity標準のシェーダではなさそうなので、
おすすめのサイトがあれば教えてほしいです。
お願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答1件
0
いくつか思いついた手を試してみましたが、いかがでしょうか?
対策なし
案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パス構成とし、第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:完全透明で別途レンダリングし、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}
投稿2019/10/14 20:27
総合スコア10811
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。