Search Unity

Is it possible to fix the Transparency + Depth sorting issue?

Discussion in 'Shaders' started by otjad, Jun 30, 2017.

  1. otjad

    otjad

    Joined:
    May 10, 2017
    Posts:
    3
    Hello, I have two transparent characters against a transparent floor that the user can view at any distance/angle.
    Thing is, when rotating or moving the camera, said objects overlap on each other. It is my understanding from this question that this is due the way the objects are sorted, based on their distance from the camera. Alas, I believe none of the solutions suggested would fix the issue in my case; would you happen to know a way to fix it or make the issue more bearable?

    Here is an example of what I am talking about:
    https://gfycat.com/MassivePepperyAppaloosa
    Thank you!
     
  2. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    You can order them manually by adjusting the queue in the material.

    Edit: Ah, the issue is between the people. There are a few options.
    1. Only draw the geometry that is at the front. Can be done easily be first drawing z-only for all people and then drawing color only. Easiest and removes the visual popping.
    2. For multiple layers you can look at order independent transparency. Can be a lot trickier.
     
    Last edited: Jun 30, 2017
  3. otjad

    otjad

    Joined:
    May 10, 2017
    Posts:
    3
    I apologize, I still struggle a lot understanding shaders. How could I first draw z-only? Would that be with a Tag within the subshader or a Blend type? My current shader is a humongous extension of the current Unity standard shader with lots of passes; I just kept on pasting code from the forums that seemed to do what I needed. It works but I am not sure if it is redundant.
    Here it is just in case:

    Code (CSharp):
    1. Shader "TransparentVertexColor" {
    2.  
    3.     Properties
    4.     {
    5.         _Color("Color", Color) = (1,1,1,1)
    6.         _MainTex("Albedo", 2D) = "white" {}
    7.  
    8.         _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5
    9.  
    10.         _Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5
    11.         _GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0
    12.         [Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel("Smoothness texture channel", Float) = 0
    13.  
    14.         [Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0
    15.         _MetallicGlossMap("Metallic", 2D) = "white" {}
    16.  
    17.         [ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0
    18.         [ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0
    19.  
    20.         _BumpScale("Scale", Float) = 1.0
    21.         _BumpMap("Normal Map", 2D) = "bump" {}
    22.  
    23.         _Parallax("Height Scale", Range(0.005, 0.08)) = 0.02
    24.         _ParallaxMap("Height Map", 2D) = "black" {}
    25.  
    26.         _OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0
    27.         _OcclusionMap("Occlusion", 2D) = "white" {}
    28.  
    29.         _EmissionColor("Color", Color) = (0,0,0)
    30.         _EmissionMap("Emission", 2D) = "white" {}
    31.  
    32.         _DetailMask("Detail Mask", 2D) = "white" {}
    33.  
    34.         _DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {}
    35.         _DetailNormalMapScale("Scale", Float) = 1.0
    36.         _DetailNormalMap("Normal Map", 2D) = "bump" {}
    37.  
    38.         [Enum(UV0,0,UV1,1)] _UVSec("UV Set for secondary textures", Float) = 0
    39.  
    40.         [HideInInspector] _Mode("__mode", Float) = 0.0
    41.         [HideInInspector] _SrcBlend("__src", Float) = 1.0
    42.         [HideInInspector] _DstBlend("__dst", Float) = 0.0
    43.         [HideInInspector] _ZWrite("__zw", Float) = 1.0
    44.  
    45.         _IntensityVC("Vertex Color Intencity", Float) = 1.0
    46.     }
    47.  
    48.     CGINCLUDE
    49.         #define UNITY_SETUP_BRDF_INPUT MetallicSetup
    50.     ENDCG
    51.  
    52.     SubShader
    53.     {
    54.         Tags{ "RenderType" = "Transparent" "PerformanceChecks" = "False" }
    55.         LOD 30000
    56.  
    57.         Pass
    58.         {
    59.             ZWrite On
    60.             ColorMask 0
    61.  
    62.             CGPROGRAM
    63.             #pragma vertex vert
    64.             #pragma fragment frag
    65.             #include "UnityCG.cginc"
    66.  
    67.             struct v2f {
    68.             float4 pos : SV_POSITION;
    69.         };
    70.  
    71.         v2f vert(appdata_base v)
    72.         {
    73.             v2f o;
    74.             o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    75.             return o;
    76.         }
    77.  
    78.         half4 frag(v2f i) : COLOR
    79.         {
    80.             return half4 (0,0,0,0);
    81.         }
    82.             ENDCG
    83.         }
    84.  
    85.         Pass
    86.         {
    87.             Name "FORWARD"
    88.             Tags{ "LightMode" = "ForwardBase" }
    89.  
    90.             Blend[_SrcBlend][_DstBlend]
    91.             ZWrite On
    92.  
    93.             CGPROGRAM
    94.             #pragma target 3.0
    95.  
    96.             #pragma shader_feature _NORMALMAP
    97.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    98.             #pragma shader_feature _EMISSION
    99.             #pragma shader_feature _METALLICGLOSSMAP
    100.             #pragma shader_feature ___ _DETAIL_MULX2
    101.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    102.             #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
    103.             #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF
    104.             #pragma shader_feature _PARALLAXMAP
    105.             #pragma shader_feature _VERTEXCOLOR_OFF _VERTEXCOLOR _VERTEXCOLOR_LERP
    106.  
    107.             #pragma multi_compile_fwdbase
    108.             #pragma multi_compile_fog
    109.  
    110.             #pragma vertex vertForwardBase_VC
    111.             #pragma fragment fragForwardBase_VC
    112.  
    113.             #include "UnityStandardCore.cginc"
    114.             #include "UnityVC.cginc"
    115.  
    116.             ENDCG
    117.         }
    118.  
    119.         Pass
    120.         {
    121.             Name "FORWARD_DELTA"
    122.             Tags{ "LightMode" = "ForwardAdd" }
    123.             Blend[_SrcBlend] One
    124.             Fog{ Color(0,0,0,0) }
    125.             ZWrite Off
    126.             ZTest LEqual
    127.  
    128.             CGPROGRAM
    129.             #pragma target 3.0
    130.  
    131.             #pragma shader_feature _NORMALMAP
    132.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    133.             #pragma shader_feature _METALLICGLOSSMAP
    134.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    135.             #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
    136.             #pragma shader_feature ___ _DETAIL_MULX2
    137.             #pragma shader_feature _PARALLAXMAP
    138.             #pragma shader_feature _VERTEXCOLOR
    139.  
    140.             #pragma multi_compile_fwdadd_fullshadows
    141.             #pragma multi_compile_fog
    142.  
    143.             #pragma vertex vertForwardAdd_VC
    144.             #pragma fragment fragForwardAdd_VC
    145.  
    146.             #include "UnityStandardCore.cginc"
    147.             #include "UnityVC.cginc"
    148.             ENDCG
    149.         }
    150.  
    151.         Pass
    152.         {
    153.             Name "ShadowCaster"
    154.             Tags{ "LightMode" = "ShadowCaster" }
    155.  
    156.             ZWrite On ZTest LEqual
    157.  
    158.             CGPROGRAM
    159.             #pragma target 3.0
    160.            
    161.             // -------------------------------------
    162.  
    163.             #pragma shader_feature _VERTEXCOLOR
    164.             #pragma shader_feature _VERTEXCOLOR_LERP
    165.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    166.             #pragma multi_compile_shadowcaster
    167.  
    168.             #pragma vertex vertShadowCaster_VC
    169.             #pragma fragment fragShadowCaster_VC
    170.  
    171.             #include "UnityStandardShadow.cginc"
    172.             #include "UnityVCShadow.cginc"
    173.  
    174.             ENDCG
    175.         }
    176.  
    177.         Pass
    178.         {
    179.             Name "DEFERRED"
    180.             Tags{ "LightMode" = "Deferred" }
    181.  
    182.             CGPROGRAM
    183.             #pragma target 3.0
    184.             #pragma exclude_renderers nomrt
    185.  
    186.             #pragma shader_feature _NORMALMAP
    187.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    188.             #pragma shader_feature _EMISSION
    189.             #pragma shader_feature _METALLICGLOSSMAP
    190.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    191.             #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
    192.             #pragma shader_feature ___ _DETAIL_MULX2
    193.             #pragma shader_feature _PARALLAXMAP
    194.             #pragma shader_feature _VERTEXCOLOR_OFF _VERTEXCOLOR _VERTEXCOLOR_LERP
    195.  
    196.             #pragma multi_compile ___ UNITY_HDR_ON
    197.             #pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
    198.             #pragma multi_compile ___ DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
    199.             #pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON
    200.  
    201.             #pragma vertex vertDeferred_VC
    202.             #pragma fragment fragDeferred_VC
    203.  
    204.             #include "UnityStandardCore.cginc"
    205.             #include "UnityVC.cginc"
    206.  
    207.             ENDCG
    208.         }
    209.  
    210.         Pass
    211.         {
    212.             Name "META"
    213.             Tags{ "LightMode" = "Meta" }
    214.  
    215.             Cull Off
    216.  
    217.             CGPROGRAM
    218.             #pragma vertex vert_meta
    219.             #pragma fragment frag_meta
    220.  
    221.             #pragma shader_feature _EMISSION
    222.             #pragma shader_feature _METALLICGLOSSMAP
    223.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    224.             #pragma shader_feature ___ _DETAIL_MULX2
    225.  
    226.             #include "UnityStandardMeta.cginc"
    227.             ENDCG
    228.         }
    229.     }
    230.  
    231.     SubShader
    232.     {
    233.         Tags{ "RenderType" = "Opaque" "PerformanceChecks" = "False" }
    234.         LOD 150
    235.  
    236.         Pass
    237.         {
    238.             Name "FORWARD"
    239.             Tags{ "LightMode" = "ForwardBase" }
    240.  
    241.             Blend[_SrcBlend][_DstBlend]
    242.             ZWrite[_ZWrite]
    243.  
    244.             CGPROGRAM
    245.             #pragma target 2.0
    246.  
    247.             #pragma shader_feature _NORMALMAP
    248.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    249.             #pragma shader_feature _EMISSION
    250.             #pragma shader_feature _METALLICGLOSSMAP
    251.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    252.             #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
    253.             #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF
    254.             #pragma shader_feature _VERTEXCOLOR_OFF _VERTEXCOLOR _VERTEXCOLOR_LERP
    255.  
    256.  
    257.             #pragma skip_variants SHADOWS_SOFT DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE
    258.  
    259.             #pragma multi_compile_fwdbase
    260.             #pragma multi_compile_fog
    261.  
    262.             #pragma vertex vertForwardBase_VC
    263.             #pragma fragment fragForwardBase_VC
    264.  
    265.             #include "UnityStandardCore.cginc"
    266.             #include "UnityVC.cginc"
    267.  
    268.             ENDCG
    269.         }
    270.  
    271.         Pass
    272.         {
    273.             Name "FORWARD_DELTA"
    274.             Tags{ "LightMode" = "ForwardAdd" }
    275.             Blend[_SrcBlend] One
    276.             Fog{ Color(0,0,0,0) }
    277.             ZWrite Off
    278.             ZTest LEqual
    279.  
    280.             CGPROGRAM
    281.             #pragma target 2.0
    282.  
    283.             #pragma shader_feature _NORMALMAP
    284.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    285.             #pragma shader_feature _METALLICGLOSSMAP
    286.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    287.             #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF
    288.             #pragma shader_feature ___ _DETAIL_MULX2
    289.  
    290.             #pragma skip_variants SHADOWS_SOFT
    291.             #pragma shader_feature _VERTEXCOLOR
    292.  
    293.             #pragma multi_compile_fwdadd_fullshadows
    294.             #pragma multi_compile_fog
    295.  
    296.             #pragma vertex vertForwardAdd_VC
    297.             #pragma fragment fragForwardAdd_VC
    298.  
    299.             #include "UnityStandardCore.cginc"
    300.             #include "UnityVC.cginc"
    301.             ENDCG
    302.         }
    303.  
    304.         Pass
    305.         {
    306.             Name "ShadowCaster"
    307.             Tags{ "LightMode" = "ShadowCaster" }
    308.  
    309.             ZWrite On ZTest LEqual
    310.  
    311.             CGPROGRAM
    312.             #pragma target 2.0
    313.  
    314.             #pragma shader_feature _VERTEXCOLOR
    315.             #pragma shader_feature _VERTEXCOLOR_LERP
    316.             #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
    317.             #pragma skip_variants SHADOWS_SOFT
    318.             #pragma multi_compile_shadowcaster
    319.  
    320.             #pragma vertex vertShadowCaster_VC
    321.             #pragma fragment fragShadowCaster_VC
    322.  
    323.             #include "UnityStandardShadow.cginc"
    324.             #include "UnityVCShadow.cginc"
    325.  
    326.             ENDCG
    327.         }
    328.  
    329.         Pass
    330.         {
    331.             Name "META"
    332.             Tags{ "LightMode" = "Meta" }
    333.  
    334.             Cull Off
    335.  
    336.             CGPROGRAM
    337.             #pragma vertex vert_meta
    338.             #pragma fragment frag_meta
    339.  
    340.             #pragma shader_feature _EMISSION
    341.             #pragma shader_feature _METALLICGLOSSMAP
    342.             #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
    343.             #pragma shader_feature ___ _DETAIL_MULX2
    344.  
    345.             #include "UnityStandardMeta.cginc"
    346.             ENDCG
    347.         }
    348.     }
    349.  
    350.     FallBack "VertexLit"
    351.     CustomEditor "StandardShaderVCGUI"
    352. }
    Thank you!
     
  4. jvo3dc

    jvo3dc

    Joined:
    Oct 11, 2013
    Posts:
    1,520
    This part would be z-only:
    Code (csharp):
    1.  
    2. ZWrite On
    3. ColorMask 0
    4.  
    So that's the first pass. The second pass would just have ZWrite Off, because it's no longer needed.
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Order Independent Transparency (OIT) is the search term you're looking for.

    To do accurate per pixel transparency sorting is extremely expensive to do on modern graphics cards, though it is possible. To do it in Unity would require essentially not using any of Unity's built in shaders, and possible not use any of Unity's built in renderer components. Pretty much no one does this outside of some tech demos and specific applications, these days it's probably cheaper to "just" do GPU based raytracing ... but that's even more work to implement.

    There are approximated OIT techniques that have gained a lot of popularity. They aren't perfectly accurate, but they're usually good enough that with out knowing they weren't accurate you wouldn't be able to tell the difference. Weighted Blended Transparency is one that a few people have released free basic implementations of, like here:
    https://forum.unity3d.com/threads/approximated-order-independent-transparency.327299/

    Another option is to abuse alpha to coverage / alpha to mask and MSAA, but it requires more than just turning it on (which is fairly easy, just make a new shader and add AlphaToMask On) as you need to manually control the mask bits so overlaps show. It also make transparency aliasing worse as it works by abusing MSAA samples.

    The "Pre-Z" option @jvo3dc is suggesting can solve the issue, but it'll also make your objects not look transparent as you won't be able to see them through each other.

    The easiest solution would be just use a blend mode that does't require sorting, like additive.
     
    Vincent454, jhocking, artincz and 2 others like this.
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,343
    Here's an example of the alpha to coverage hack. You must have 4x MSAA anti-aliasing turned on for this to work. Only two objects will overlap, after that it's fully opaque, but both objects will individually be ~80% opaque unless they overlap. For your example above you'll need each character to be using materials with a different "Object" setting, but leave the ground using the material it currently has.

    Code (CSharp):
    1. Shader "Unlit/CoverageMask4XMSAA" {
    2. Properties {
    3.     _MainTex ("Base (RGB)", 2D) = "white" {}
    4.     [Enum(A, 14, B, 13, C, 11, D, 7)] _Coverage ("Coverage Object", Int) = 14
    5. }
    6.  
    7. SubShader {
    8.     Tags { "RenderType"="Opaque" }
    9.     LOD 100
    10.    
    11.     Pass {
    12.         AlphaToMask On
    13.  
    14.         CGPROGRAM
    15.             #pragma vertex vert
    16.             #pragma fragment frag
    17.             #pragma target 5.0
    18.             #pragma multi_compile_fog
    19.            
    20.             #include "UnityCG.cginc"
    21.  
    22.             struct appdata_t {
    23.                 float4 vertex : POSITION;
    24.                 float2 texcoord : TEXCOORD0;
    25.             };
    26.  
    27.             struct v2f {
    28.                 float4 vertex : SV_POSITION;
    29.                 float2 texcoord : TEXCOORD0;
    30.                 UNITY_FOG_COORDS(1)
    31.             };
    32.  
    33.             sampler2D _MainTex;
    34.             float4 _MainTex_ST;
    35.            
    36.             v2f vert (appdata_t v)
    37.             {
    38.                 v2f o;
    39.                 o.vertex = UnityObjectToClipPos(v.vertex);
    40.                 o.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);
    41.                 UNITY_TRANSFER_FOG(o,o.vertex);
    42.                 return o;
    43.             }
    44.  
    45.             uint _Coverage;
    46.            
    47.             fixed4 frag (v2f i, out uint mask : SV_Coverage) : SV_Target
    48.             {
    49.                 fixed4 col = tex2D(_MainTex, i.texcoord);
    50.                 UNITY_APPLY_FOG(i.fogCoord, col);
    51.                 UNITY_OPAQUE_ALPHA(col.a);
    52.                 mask = _Coverage;
    53.                 return col;
    54.             }
    55.         ENDCG
    56.     }
    57. }
    58.  
    59. }
     
    Vincent454, Shinyclef and otjad like this.
  7. otjad

    otjad

    Joined:
    May 10, 2017
    Posts:
    3
    Thank you so much for your responses!

    I tried both implementations, the "ZWrite On" during the first pass and the alpha coverage hack (Really interesting stuff!). The thing is that I also need to display the vertices color which, along the alpha values, vary constantly each frame and I wasn't able to integrate this into your solutions :(

    Nevertheless, @bgolus, the link that you provided in your first post mentioned this GitHub project that seems rather frail and hacky but gives great results! Somehow I was able to add vertex color without breaking it.

    Also, thank you for dropping the "OIT" term too, I learned a lot from googling it!
     
    Vincent454 and Harinezumi like this.