Issues with Transparency on Transparency

I am designing a greenhouse scene for my portfolio (I stripped it down a few days ago), and have hit a pretty large issue graphically.
when I use any kind of object with a transparent material over another object with a transparent material, it appears the order gets mixed up and one is rendered over the other (in the wrong order).

Please ignore the fact that the screenshot is largely untextured, I have been trying to focus on this issue for a few hours now.

In this case, the Ivy is physically over the glass, infront of it, but is being rendered as if it were behind the glass, this is evident by looking at the solid frame versus the glass there the Ivy intersects the two.

Does anyone know how to fix this, it appears in scene and game view and is really limiting design?

Sorting order problems are a normal thing, unfortunately.
Use Cutout type of transparency for the leaves. It will be little difference visually. Cutout renders almost like a regular solid mesh, though, so no usual transparency problems.

1 Like

This worked well, thanks.
Is this the only way to achieve this? What if I am placing objects that need transparency specifically? Is there any way to correct this?

I don’t know if there’s any way to influence sorting in Unity Editor.

In your own shader, you could use “Queue”=“Transparent+AMOUNT”.
Then use this shader for objects that need to be always in front of other transparents.

Normal code:

SubShader {
     Tags {
       "RenderType" = "Transparent"
       "Queue" = "Transparent"
     }
     Fog { Mode Off }

Your modified sorting priority:

SubShader {
     Tags {
       "RenderType" = "Transparent"
       "Queue" = "Transparent+10"
     }
     Fog { Mode Off }

Here’s a replacement for a Standard PBR shader with Fade transparency.
Change line 39 for your own sorting priority (e.g. Transparent+10).

// Author: Oskar Swierad
// 11 June 2015

Shader "CustomStandard/Basic/Fade"
{
   Properties
   {
     _Color("Color", Color) = (1,1,1,1)
     _MainTex("Albedo", 2D) = "white" {}

     // _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5   // for Cutout

     _MetallicGlossMap("Metallic", 2D) = "white" {}

     _BumpScale("Normal Strength", Float) = 1.0
     _BumpMap("Normal Map", 2D) = "bump" {}

     // _ParallaxMap ("Height Map", 2D) = "black" {}
     // _Parallax ("Height Scale", Range (0.005, 0.08)) = 0.02

     _OcclusionMap("Occlusion", 2D) = "white" {}
     _OcclusionStrength("Occ Strength", Range(0.0, 1.0)) = 1.0

     // Blending state
     // _Mode (0, 1, 2, 3) maps to (Opaque, Cutout, Fade and Transparent)
     [HideInInspector] _Mode ("__mode", Float) = 3.0
     [HideInInspector] _SrcBlend ("__src", Float) = 1.0
     [HideInInspector] _DstBlend ("__dst", Float) = 0.0
     [HideInInspector] _ZWrite ("__zw", Float) = 1.0
   }


   SubShader
   {
     Tags {
       "RenderType" = "Transparent" // http://docs.unity3d.com/Manual/SL-ShaderReplacement.html
       "Queue" = "Transparent+0"   // http://docs.unity3d.com/Manual/SL-SubShaderTags.html
     }
     LOD 300

     CGPROGRAM
     #pragma target 3.0
     #include "UnityPBSLighting.cginc"
     #include "UnityStandardUtils.cginc"
     #define _GLOSSYENV 1
     // #define _ALPHATEST_ON   // for Cutout
     #pragma surface surf Standard addshadow alpha:fade // or 'alphatest:_Cutoff' or 'alpha:premul' for Transparent

     uniform half4 _Color;
     uniform sampler2D _MainTex;
     // uniform half _Cutoff;   // for Cutout

     uniform sampler2D _MetallicGlossMap;
     uniform float _BumpScale;
     uniform sampler2D _BumpMap;
     uniform fixed _OcclusionStrength;
     uniform sampler2D _OcclusionMap;
     //uniform float _Parallax;
     //uniform sampler2D _ParallaxMap;



     struct Input {
       float2 uv_MainTex;
       // float4 color : COLOR;     // enable to use vertex color
       // float3 viewDir;     // required when using parallax (height map)
     };



     void surf (Input IN, inout SurfaceOutputStandard o )
     {
       // const fixed3 vertexColor = IN.color.rgb;

       half2 uv = IN.uv_MainTex;
       // half2 parallax = ParallaxOffset1Step( tex2D( _ParallaxTex, uv ), _ParallaxStrength, IN.viewDir );
       // uv += parallax;

       const half2 metalGloss = tex2D( _MetallicGlossMap, uv ).ra; // metalness is in R channel, smoothness is A

       // OUTPUTS
       o.Albedo = _Color.rgb * tex2D( _MainTex, uv ).rgb; // * vertexColor;
       o.Alpha = _Color.a * tex2D( _MainTex, uv ).a;
       o.Normal = UnpackNormal( _BumpScale * tex2D( _BumpMap, uv ) );
       o.Metallic = metalGloss.x;
       o.Smoothness = metalGloss.y;
       o.Occlusion = LerpOneTo( tex2D( _OcclusionMap, uv ).g, _OcclusionStrength ); // occlusion is in G channel
     }


     ENDCG
   }

   FallBack "Standard"
}
1 Like

You can change the sorting order (render queue) on a per-material basis. You can either do it through scripting, or by looking at the material with the inspector in debug mode, and changing the “custom render queue” value.

You get to debug mode by selecting the little drop-down in the inspector’s upper right corner, next to the lock symbol.

The render queue of objects influence how they’re rendered - objects on a queue with ID <= 2500 are rendered front-to-back, while objects with a higher queue are rendered back-to-front. AlphaTest is at 2450, while Transparent is 3000, so you’ll get different results between those two.

See more here.

3 Likes

Nice trick with the Debug inspector mode

That approach solves it for one side, but if you then go to the other side it will not anymore be correct.

The problem is probably that, while Unity sorts transparent objects back to front, that doesn’t solve overlapping transparent objects.

What I’d suggest is splitting your plant into two meshes, and placing one mesh in front of the glass and one mesh behind, so it still looks the same, but unity can sort the two meshes for in front/behind.

1 Like

Dantus: I see. What is the proper approach, or at least more correct?

Split it up us much as needed, such that the sorting of Unity can handle it.

I expect that the glass in the picture is one mesh. If it is split up into e.g. three parts, one on the left, one on the right and one below the plant, it becomes a lot easier to handle it. The plant itself should be split up as well depending on the positions from which it can be seen.

It is very annoying to do that, that’s out of question. But if a general solution is needed, this is the only way to handle it.

1 Like

You are a lifesaver @Baste …THANK YOU!