Search Unity

Alpha transparency self sorting in Unity5

Discussion in 'Shaders' started by SyoS, Apr 12, 2015.

  1. SyoS

    SyoS

    Joined:
    Apr 12, 2015
    Posts:
    5
    I am trying to create a transparent shader using the alpha map.
    I referred to the following threads and manuals.

    http://forum.unity3d.com/threads/why-diffuse-transparent-diffuse-alpha-1.150048/
    http://forum.unity3d.com/threads/al...-sorting-issue-help-really-appreciated.68636/
    http://docs.unity3d.com/Manual/SL-CullAndDepth.html

    And I wrote a simple prototype shader.

    Code (CSharp):
    1. Shader "Transparent/Diffuse ZWrite" {
    2.     Properties {
    3.         _Color ("Main Color", Color) = (1,1,1,1)
    4.         _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    5.     }
    6.  
    7.     SubShader {
    8.         Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
    9.         //Tags { "Queue"="AlphaTest" "IgnoreProjector"="true" "RenderType"="TransparentCutout" }
    10.         LOD 200
    11.         Cull Off
    12.         Blend SrcAlpha OneMinusSrcAlpha
    13.  
    14.         // extra pass that renders to depth buffer only
    15.         Pass {
    16.             ZWrite On
    17.             ColorMask 0
    18.             Cull Off
    19.         }
    20.        
    21.         ZWrite Off
    22.         Cull Off
    23.         CGPROGRAM
    24.         #pragma surface surf Standard fullforwardshadows  alpha:blend
    25.         //#pragma surface surf Standard fullforwardshadows alphatest:_Cutout
    26.         //#pragma surface surf Standard fullforwardshadows alpha:fade
    27.  
    28.         sampler2D _MainTex;
    29.         fixed4 _Color;
    30.  
    31.         struct Input {
    32.             float2 uv_MainTex;
    33.         };
    34.  
    35.         //void surf (Input IN, inout SurfaceOutput o) {
    36.         void surf (Input IN, inout SurfaceOutputStandard o) {
    37.             fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    38.             o.Albedo = c.rgb;
    39.             o.Alpha = c.a;
    40.         }
    41.         ENDCG
    42.         // paste in forward rendering passes from Transparent/Diffuse
    43.         //UsePass "Transparent/Diffuse/FORWARD"
    44.     }
    45.  
    46.     Fallback "Transparent/VertexLit"
    47. }
    As a result, it was able to draw the depth, there is a problem with the transparency by alpha.
    Please see the attached image (also to compensate for my strange English).



     The results of the rendering seem to be different from unity4.
    Although polygon has become transparent by the texture, it "clip" to the object behind should look.(Shader seems to ignore the object in the back really.)

    What can I do to solve this problem?
    Thank you.
     
  2. SyoS

    SyoS

    Joined:
    Apr 12, 2015
    Posts:
    5
    Any idea?
    Are there the people having a similar problem?o_O
     
  3. UnityGuillaume

    UnityGuillaume

    Unity Technologies

    Joined:
    Mar 16, 2015
    Posts:
    123
    Well it seems to behave as it should...


    You have Zwrite enabled, meaning a pixel rendered will write its depth in the Zbuffer, and for any other pixel at the same place, it will be discarded if its depth is greater than the one in the depth buffer.

    What is happening is that your plane that stick toward the cam get rendered first, and pixel write their depth (even with alpha == 0, it just make it blend with that's already there, i.e. the background, but the pixel still rendered & write in depth buffer)
    So when the plane facing the cam get rendered, its pixel behind don't even reach the pixel shader stage, they are discarded because for the GPU, there is a pixel in front. So they don't get blended with that's already there. Shader DO ignore the object behind, the GPU don't send those pixel to the pixel shader

    That why you disable depth write for transparent mesh usually.
     
  4. SyoS

    SyoS

    Joined:
    Apr 12, 2015
    Posts:
    5
    Thank you for reply:)

    Perhaps, I was somehow able to understand.
    That means, Is it that it cannot sort a transparent object?
    For example, does the particle system sort it by other methods?
     
  5. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Seems right to me. A transparent object will get clipped correctly by opaque zwrite geometry in the right places. For transparent sorting, it's fine if it's a separate object, you cannot sort transparent object without 2 passes (ie one pass for alpha cutout and one pass for drawing blended colour).

    Otherwise if each transparent object is an independent mesh it will be sorted by view distance or whatever. Problems arise when you combine transparent meshes.
     
  6. Noisecrime

    Noisecrime

    Joined:
    Apr 7, 2010
    Posts:
    2,054
    Transparency is problematic for real-time graphics. It is technically possible to do, but requires such overhead and additional work that compromises must be made. That said there are also some tricks that can disguise the problem such as using additive blending instead of alpha blending, but that's no use if you need alpha blending.

    In general a real-time 3D engine will only sort transparent models by depth ( and then render back to front), but it will make no attempt to sort polygons within a model/mesh. The reason for not sorting per polygon is that it can break batching (i.e. if you mesh uses more than 1 material), secondly it can be an expensive process and finally intersecting polygons can never have a correct draw order unless they are divided/split (i.e The Painters Algorithm issue). Further more even if you sorted within a mesh it does not then resolve the problems of overlapping meshes. For that to work you'd need to sort against both meshes and .. well you can see the madness that can quickly escalate to.

    Now the Unity particle system offers two methods that may solve the sorting issue. First you can use additive blending, which is draw order independent, meaning it does matter which triangles are drawn first the result is always correct. This can be great for fx like explosions or sparks, but is no use if you need normal alpha blending. The second method is that it provides the option to self sort the triangles within the particle system, which mostly works but can be expensive on the cpu. Unfortunately this second method suffers from the same issues outlined above in terms of sorting polygons within a mesh.

    So where does that leave you?

    Well the simplest fix, though not a very efficient one, would be to divide up each of you three planes into four quadrants each. In other words split each plane into 4 quadrants and keep each as a separate model. That way the Unity sorting *should* ensure the correct draw order. If this is for a different model than the one you've shown then the same technique *may* help, but its unlikely and it will just become more in-efficient.

    You could look into writing your own script for dynamic polygon sorting within a mesh. In fact i'm sure someone would have already done this, so maybe just search google.

    There are other options such a blended order independent transparency, but those are generally more complex to set up.
     
  7. SyoS

    SyoS

    Joined:
    Apr 12, 2015
    Posts:
    5
    Thank you ,hippocoder and Noisecrime.:) It became clearer.

    I seemed to think about it slightly lightly...:confused:
    CPU/GPU power seems to be necessary to get the result that I thought about at first than I expected it.
    So I decide to think including other approach.
    (Possibly I should have said this first, but I was going to make a shader for the cloud.)


    hippocoder, may I ask you a question one more?(Because you like a particle of expert.)
    When I attached the shader using normal map to a particle, it was like a normal direction has been strange.
    Does the particle system not calculate the tangent?
    (If I should make a thread separately, I will do so. sorry.)
     
  8. hippocoder

    hippocoder

    Digital Ape

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I doubt particle system calculates tangents, so you would want to do it within shader instead. Did you try the bent normal option?
     
  9. SyoS

    SyoS

    Joined:
    Apr 12, 2015
    Posts:
    5
    I see. It seems there is a need to calculate, if I want it...
    What is "bent normal option"? Is it " Renderer > Normal Direction(float 0~1.0)" ?