Search Unity

Depth of Field, Unity 5, and Transparent Shaders

Discussion in 'Shaders' started by CryogenicEntertainment, Mar 5, 2015.

  1. CryogenicEntertainment

    CryogenicEntertainment

    Joined:
    Dec 7, 2014
    Posts:
    4
    I find myself with the need to have both the DoF image effect and a transparent shader in Unity 5. The trouble that I am having is that when the custom transparent shader is rendered, it is not being seen by the DoF, so it is always rendered as being blurred (even when it should be in focus). In prior versions of unity, I was able to fix this by fiddling around with the tags of the shader.

    If you have any idea on how to get this to work properly or if you know that it is impossible, I would really love to know. Any help would be invaluable. (I need to choose to stay on Unity 4.6 or to update my project to 5, and this is the only hangup that I am having.) Thank you for your time!
     
    deus0 likes this.
  2. jackson31

    jackson31

    Joined:
    Aug 25, 2010
    Posts:
    28
    I have the same issue.
    I used to have a working custom shader which was transparent but still was considered by DoF as geometry, meaning it didn't get blurred out even while inside the focus area.

    Since upgrading to 5 this shader has stopped working and there's no stock U5 shader which has the behavior I need :(
     
  3. jackson31

    jackson31

    Joined:
    Aug 25, 2010
    Posts:
    28
    I should also add, not only are the transparent shaders never taken into consideration by DoF, they also do not cast shadows unless in the horribly ugly "cut-out" or masked mode
     
  4. varfare

    varfare

    Joined:
    Feb 12, 2013
    Posts:
    227
    Unity5 does not support shadow casting and receiving for transparent objects. I've seen Unity dev saying that this will be added in one of the Unity 5 updates.

    About that dof... You should check out DOF code. Unity5 have brand new image effects which might be different from 3/4 DOF. Maybe it is not taking transparent objects into account since they don't do Zwrite?
     
    deus0 likes this.
  5. jackson31

    jackson31

    Joined:
    Aug 25, 2010
    Posts:
    28
    Yes, I know the reason the DoF doesn't consider the transparent content is because it doens't Zwrite, but right now there doesn't seem to be any way to create a custom transparent shader that does ZWrite, look around this board, plenty of other people are complaining that their custom shaders have broken after moving to unity5.
    The unity dev's need to address this
     
  6. CryogenicEntertainment

    CryogenicEntertainment

    Joined:
    Dec 7, 2014
    Posts:
    4
    How are people doing this?

     
  7. brianasu

    brianasu

    Joined:
    Mar 9, 2010
    Posts:
    369
    DOF uses the depth buffer which transparent shaders don't write to. So it's using the depth of whatever is behind that flame. That is why the other flame is more if focus since it's in front of a closer object. If you look at the flame all the way to the left you can see that it's incorrect.

    If you had a transparent glass wall. and write that to the depth buffer then the transparent shape will be blurred properly but whatever is seen through the object will not be correct. It will look like a non blurred portal.

    You would need to use multiple passes to get it to work properly.
     
  8. Froghuto

    Froghuto

    Joined:
    Oct 4, 2012
    Posts:
    61
    I have the same problem, upgraded to Unity 5 and my old custom transparent shaders + depth of field no longer work.
    So in current Unity 5 there is no way to get that to work? some kind of workaround perhaps?
     
  9. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    As people have pointed out, DoF + non cutout stuff WILL get artifacts. However you CAN write to depth buffer with transparent shaders.
    (Very simple shader that is transparent AND draws to depth buffer!)
    Code (CSharp):
    1. Shader "Custom/Test" {
    2.     Properties {
    3.         _Color ("Color", Color) = (1,1,1,1)
    4.         _MainTex ("Albedo (RGB)", 2D) = "white" {}
    5.     }
    6.     SubShader {
    7.         Tags { "RenderType"="Transparent" "Queue"="Transparent+10"}
    8.         LOD 200
    9.         Zwrite On
    10.         Blend SrcAlpha OneMinusSrcAlpha
    11.         Pass {
    12.             CGPROGRAM
    13.             #pragma vertex vert_img
    14.             #pragma fragment frag
    15.  
    16.             #include "UnityCG.cginc"
    17.            
    18.             uniform sampler2D _MainTex;
    19.             float4 _Color;
    20.             fixed4 frag(v2f_img i) : SV_Target {
    21.                 return tex2D(_MainTex, i.uv) * _Color;
    22.             }
    23.             ENDCG
    24.         }
    25.     }
    26.     FallBack "Diffuse"
    27. }
    28.  
    As for writing transparent shaders that do z-write, well, it's fully doable! Even getting them to BOTH recieve AND cast shadows. (Tho if doing both there will be some artifacts that are noticable when the transparent object and what is behind constast alot.) I know of a better solution without hacking to much of the pipeline for shadow recieving but havn't gotten around to figuring out how to bypass unity's "shadow gather" step.

    Maybe this would work, but how would you handle the problem of double blurring? (I guess outputting the resulting alpha could work, but overlapping transparent objects are not solved...)

    The "real" problem pretty much can't be solved with the way we render graphics today in a performant way.
    My guess as for how unity did in their demo, they let the Fires get blurred out, and made sure the stick the torch was based on was opaque, making it not feel so bad?

    Another option is to do the DoF after opaque things, then use mipmaps to "blur" the transparent stuff as it's being rendered based on distance.


    This is probably one of the best things they have done, they stopped supporting stuff that was so out of date it was ridiculous! Really, with a MAJOR update, it's quite expected to loose compatability, tbh, it's actually awesome we can at ALL port our projects so well!
     
  10. Froghuto

    Froghuto

    Joined:
    Oct 4, 2012
    Posts:
    61
    Thanks Zicandar for the shader, sadly it does not seem to work. I'm a shader noob so I might have done something wrong, but "ZWrite On" does not seem to do the trick anymore, it seems shaders have to have a "ShadowCaster" Pass for it to work (see here).
     
  11. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    Code (CSharp):
    1. FallBack "Diffuse"
     
    pottering likes this.
  12. Froghuto

    Froghuto

    Joined:
    Oct 4, 2012
    Posts:
    61
    I experimented a bit more and it seems that the shader will just not work with DoF as long as its
    Queue is set to Transparent, it will work when set to Geometry. It seems Unity 5 will just not "throw shadows" for transparent objects. I also tried with Unity's new Standard shader, it works in DoF when set to Opaque, but it no longer works when set to Transparent.
     
  13. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    Well, transparent stuff CAN write to the depth buffer. It's simply that the way unity currently seems to handle the depth buffer READING (for effects) is to copy it out ("resolve depth") just after all opaque geometry has been rendered.

    There ARE workarounds for this:
    (I did the following to handle semi-transparent stuff both casting AND recieving shadows, should hopefully work somewhat ok for this case):
    Simple shader / Diffuse with separate mask texture
    The last few posts describe what I did, and the problems. However for DoF this could potentially be enough.
    (Or quite the opposite, nowhere close to good because of it require opaque areas).

    The only "real" solution I can come up with would be to add/modify that "depth buffer" yourself after unity has copied it.
     
    pottering likes this.
  14. Froghuto

    Froghuto

    Joined:
    Oct 4, 2012
    Posts:
    61
    I tried the shader of the post you referenced - it does throw shadows, but still does not work for DoF. Do you have any idea if it would be possible to modify the depth texture before effects read from it, to "render" transparent objects into it?
    Thanks for your help so far!
     
  15. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    I've been considering just that, POSSIBLY with 2 passes, one for the depth, one for the transparent stuff. But that should more or less be what my shader did.
    I'd THINK the simpler solution would be to copy the "real" depth buffer into the depth texture that DoF reads from.
    Another possibility would be to set the DoF depth texture up as a render target, then write to it using DrawMeshNow or similar.
    I sadly don't really have time currently to test these things, but they shouldn't be to hard to test if you want to.
     
  16. OlliQueck

    OlliQueck

    Joined:
    Apr 11, 2013
    Posts:
    49
    i'm currently having the same issue with a custom image effect. What i need is a fragment shader on an object that outputs RGB, Alpha and Depth. Then i comp them together in a post-shader. Can't find any way to do this without using multiple passes... but developing for mobile i'm afraid this could kill performance becouse basicly the object-shader takes 90% of the screen.
     
  17. OlliQueck

    OlliQueck

    Joined:
    Apr 11, 2013
    Posts:
    49
    ok wow this is crazy, thank you very much zicandar your post finally helped me. NEVER FORGET THE DAMN "Fallback "Diffuse" AT THE END!! ... i still have no clue why a "fallback" function has an effect on the shader above...
     
  18. Zicandar

    Zicandar

    Joined:
    Feb 10, 2014
    Posts:
    388
    Your more then welcome, it's an easy thing to forget!

    You can output a MODIFIED depth value from the pixel shader if you need to btw :)

    I sadly do.
    Unity in forward mode runs a separate depth pass, and when it see's its a transparent shader doesn't draw to it.
    In deferred mode it uses the "real" depth buffer, BUT it stores away a copy of it around the time of lighting, this is in a lot of cases useful as it allows us to not get our depth thrashed by stuff that need a depth pre-pass to not shine through themselves.

    Sadly it does result in issues for us, a fallback to a CUTOUT shader might help however.
     
    Last edited: May 22, 2015
  19. brianasu

    brianasu

    Joined:
    Mar 9, 2010
    Posts:
    369
  20. Brendonm17

    Brendonm17

    Joined:
    Dec 9, 2013
    Posts:
    43
    Bump

    It's still been a while since unity 5 released. I can't see how this is still an issue! I'm trying to use the dof image effect but the billboard trees keep rendering as blurred out. Any help is appreciated...
     
  21. varfare

    varfare

    Joined:
    Feb 12, 2013
    Posts:
    227
    Report this on bugtracker.
     
  22. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,799
    This is a problem, because then it would need two depth pixels for 1 nomal pixel.

    (a semi transparent pixel has should have both the depth of the background and the transparent surface, since both show).

    That's why it's problematic and AFAIK I don't think there is an elegant solution for this yet.
     
  23. brianasu

    brianasu

    Joined:
    Mar 9, 2010
    Posts:
    369
    Think of a piece of glass. The glass itself would have to be in focus. But the image visible through it would have to be out of focus.

    Like AcidArrow said you would need to calculate depth for the glass and depth for everything behind it. If you had multiple overlapping pieces of glass it would be even more complex.

    Kinda like this. You can see the glass is in focus but what is seen through has DOF. I think there might be some complex way like depth peeling to solve this problem but it would be extremely heavy.
     
    AcidArrow likes this.
  24. Brendonm17

    Brendonm17

    Joined:
    Dec 9, 2013
    Posts:
    43
    I honestly don't need anything like depth peeling, my objects aren't even transparent. I don't understand why a billboard is being rendered like a transparent object.
     
  25. deus0

    deus0

    Joined:
    May 12, 2015
    Posts:
    256
    Anyone find out yet?