Search Unity

  1. We want you to join us at GDC this year! Take a peek at all of the events we will be hosting during the week of GDC.
    Dismiss Notice
  2. Tell us about your experience here and you’ll get early access to the 2018 Game Studios report + more goodies.
    Dismiss Notice
  3. Unity 2017.3 has arrived! Read about it here.
    Dismiss Notice
  4. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice
  5. We've closed the job boards. If you're looking for work, or looking to hire check out Unity Connect. You can see more information here.
    Dismiss Notice

Transparent shader for DOF - needs to add to zbuffer

Discussion in 'Shaders' started by trzmiel, Feb 13, 2018.

  1. trzmiel

    trzmiel

    Joined:
    Nov 5, 2013
    Posts:
    28
    OK, I really can't solve this problem and I need your help.
    Here is my situation: 2 cells with an opaque nucleus and semi-transparent envelope (see attached image).
    The first bigger cell is in front of the smaller one. The Depth of Field effect acts correctly on nucleus - the foreground nucleus is blurred and the background nucleus is in a sharp zone. The problem is with semitransparent envelopes. Transparent shader does not modify z-buffer and that's why each envelope is blurred. The effect would be acceptable to me if the first/closest envelope would set z-buffer to its depth.
    How to do this?
    My transparent shader code:
    Code (CSharp):
    1. Shader "CHMIEL/Transparent Diffuse ZWrite" {
    2.    
    3.     Properties{
    4.         _Color("Main Color", Color) = (1,1,1,1)
    5.         _MainTex("Base (RGB) Trans (A)", 2D) = "white" {}
    6.     }
    7.  
    8.         SubShader{
    9.         Tags{ "Queue" = "Transparent-20" "IgnoreProjector" = "True" "RenderType" = "Transparent" }
    10.         LOD 200
    11.         ZWrite On
    12.         ZTest LEqual
    13.  
    14.         CGPROGRAM
    15. #pragma surface surf Lambert alpha
    16.  
    17.         sampler2D _MainTex;
    18.     fixed4 _Color;
    19.  
    20.     struct Input {
    21.         float2 uv_MainTex;
    22.     };
    23.  
    24.     void surf(Input IN, inout SurfaceOutput o) {
    25.         fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    26.         o.Albedo = c.rgb;
    27.         o.Alpha = c.a;
    28.     }
    29.     ENDCG
    30.     }
    31.  
    32.         Fallback "Transparent/VertexLit"
    33. }
     

    Attached Files:

  2. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    21,138
    Transparency writes in forward pass after depth and opaque so any depth of field will only affect opaque. There are several strategies for tackling it but that needs much more information because they're all hacks.

    Looking at the picture, I would instead modify the shader to get depth from position and blur it yourself to match, either via lower mip maps or with lerping between a sharp cell* image for focused parts and a blurry cell* image for unfocused parts.

    * semi-transparent envelope
     
  3. trzmiel

    trzmiel

    Joined:
    Nov 5, 2013
    Posts:
    28
    Oh, is it impossible to render the transparent objects as transparent but with modifying z-buffer as opaque objects do?
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    3,904
    Unity does not include objects that are part of the transparent queues in the depth texture used by the DOF effect. The depth texture isn't necessarily the same as the z buffer / depth buffer, though it generally matches the depth buffer just after the opaque queues have finished rendering. If you're rendering using the deferred path the depth texture is a copy of the depth buffer, and has to match the depth of the opaque objects that have rendered for opaque lighting to work properly. For the forward path the depth texture is generated before rendering the main scene as a separate render pass of the entire view. This may or may not match the depth buffer from the opaque pass, but it still only contains those objects rendered during the opaque queue.

    If you want to inject transparent objects into the depth texture you would need to either render your transparent objects as part of the opaque queue, which may cause problems with sorting, or you can render another object during the opaque queue that doesn't actually render anything visible during the opaque pass, but has a shadow caster pass or Fallback "VertexLit".