Search Unity

Depth buffer with orthographic camera?

Discussion in 'Shaders' started by pixpusher2, Sep 18, 2015.

  1. pixpusher2

    pixpusher2

    Joined:
    Oct 30, 2013
    Posts:
    121
    I came across this cool shader effect (shader code inside the link). The depth buffer fading effect works well on perspective camera, but not with orthographic camera mode I'm using.

    Is there an alternative way to recreate the Y-depth effect on the ortho camera? I couldn't find anything on Google but I may be using the wrong keywords.

    Any ideas or keywords to search for would help. Thanks!

    depthbuffer.jpg
     
  2. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    Why this happens:
    Perspective cameras show objects larger up close and smaller as they get farther away. Because of this, you get a closer look at objects close to the camera, so you want better depth quality on them. For this reason, you have logarithmic depth, which gives better accuracy up-close at the cost of lower depth-quality farther away from the camera. (Nobody will notice those 2 pixels z-fighting in the distance anyway)

    Orthographic cameras use linear depth because you can see object just the same no matter how far away they are from the camera, so there's no reason to have better accuracy on closer objects.

    With logarithmic depth, you end up using depth values 0 through 0.7 in just the first 10% of the frustum and distribute the rest throughout the remaining 90% of the frustum. Linear depth goes from 0 to 1 linearly. (Let me know if you'd like me to explain any of this better)

    How to fix it:
    Line 39 of that shader is:
    Code (CSharp):
    1. float depth = Linear01Depth (tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)).r);
    "Linear01Depth" converts logarythmic depth into linear depth, but you already have linear depth on an orthographic camera, so just remove that function call. The result should be this:
    Code (CSharp):
    1. float depth = tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)).r;

    I have not tested this. Let me know how it goes!
     
    chingwa likes this.
  3. pixpusher2

    pixpusher2

    Joined:
    Oct 30, 2013
    Posts:
    121
    Thanks for the explanation Gambit_MSplitz! I get what you mean. :)

    I've tested the changes, but the result remains the same for ortho camera (the effect no longer works in perspective camera though, as expected). The ortho camera depth buffer seems to be either 0 or 1, but nothing in between? :confused:

    I'll try fiddling with it more. Thanks!

    Update:
    Lowering the ortho camera's Clipping Planes to between 0.2 and 3.5 helped somewhat (no effect on the sphere though), but now the scene objects clip really badly. Any ideas? Or should I just drop it?

    with LinearEyeDepth
    depth.jpg

    without LinearEyeDepth
    depth.jpg


    Update 2:
    Getting close! Made some code changes to make it work with normal Clipping Planes value of 0.01 to 1000.
    Code (CSharp):
    1. float sceneZ = tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)).r * 40; //multiply with value
    2.  
    3. float partZ = i.projPos.y; //changed to Y-axis

    There's still an issue of the effect being more apparent when object is at the bottom of the screen. Will try to figure this out...
    depth.jpg
     
    Last edited: Sep 19, 2015
  4. pixpusher2

    pixpusher2

    Joined:
    Oct 30, 2013
    Posts:
    121
    I did a hackish fix to reduce the Z-axis fading on ortho camera. I'll just consider this solved unless there's a better solution. :)

    Code (CSharp):
    1. //Highlights intersections with other objects
    2. Shader "Custom/IntersectionHighlights"
    3. {
    4.     Properties
    5.     {
    6.         _RegularColor("Main Color", Color) = (1, 1, 1, .5) //Color when not intersecting
    7.         _HighlightColor("Highlight Color", Color) = (1, 1, 1, .5) //Color when intersecting
    8.         _HighlightThresholdMax("Highlight Threshold Max", Float) = 1 //Max difference for intersections
    9.         _ZBias("Highlight Z Bias", Float) = 2.5    //Balance out the Z-axis fading
    10.     }
    11.     SubShader
    12.     {
    13.         Tags { "Queue" = "Transparent" "RenderType"="Transparent"  }
    14.         Pass
    15.         {
    16.             Blend SrcAlpha OneMinusSrcAlpha
    17.             ZWrite Off
    18.             Cull Off
    19.             CGPROGRAM
    20.             #pragma target 3.0
    21.             #pragma vertex vert
    22.             #pragma fragment frag
    23.             #include "UnityCG.cginc"
    24.             uniform sampler2D _CameraDepthTexture; //Depth Texture
    25.             uniform float4 _RegularColor;
    26.             uniform float4 _HighlightColor;
    27.             uniform float _HighlightThresholdMax;
    28.             uniform float _ZBias;
    29.             struct v2f
    30.             {
    31.                 float4 pos : SV_POSITION;
    32.                 float4 projPos : TEXCOORD1; //Screen position of pos
    33.             };
    34.             v2f vert(appdata_base v)
    35.             {
    36.                 v2f o;
    37.                 o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    38.                 o.projPos = ComputeScreenPos(o.pos);
    39.                 return o;
    40.             }
    41.             half4 frag(v2f i) : COLOR
    42.             {
    43.                 float4 finalColor = _RegularColor;
    44.                 //Get the distance to the camera from the depth buffer for this point
    45.                 float sceneZ = tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)).r * 400;
    46.  
    47.                 //Actual distance to the camera
    48.                 float partY = i.projPos.y + (i.projPos.y/_ZBias);
    49.  
    50.                 //If the two are similar, then there is an object intersecting with our object
    51.                 float diff = (abs(sceneZ - partY)) / _HighlightThresholdMax;
    52.                 if (diff <= 1)
    53.                 {
    54.                     finalColor = lerp(_HighlightColor, _RegularColor, diff);
    55.                 }
    56.                
    57.                 half4 c;
    58.                 c.r = finalColor.r;
    59.                 c.g = finalColor.g;
    60.                 c.b = finalColor.b;
    61.                 c.a = finalColor.a;
    62.                 return c;
    63.             }
    64.             ENDCG
    65.         }
    66.     }
    67.     FallBack "VertexLit"
    68. }
     
  5. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    So in your "update 2" you say the effect is darker towards the bottom of the screen.. that's because you have your camera at an angle so the objects at the bottom of the screen are closer to the camera.

    I could be wrong, but it seems the only problem you have now is the rate at which you fade from pink to transparent. Since the falloff is not linear, I think something in the calculation is still expecting you to use a perspective camera.

    This is just a wild guess, but try changing:
    Code (CSharp):
    1. float depth = tex2Dproj(_CameraDepthTexture, UNITY_PROJ_COORD(i.projPos)).r;
    to
    Code (CSharp):
    1. float depth = tex2D(_CameraDepthTexture, (i.projPos)).r;
     
  6. pixpusher2

    pixpusher2

    Joined:
    Oct 30, 2013
    Posts:
    121
    Sadly the Z-distance fading is still there after replacing that code.
    Thanks for helping out though! :)

    Just realized the effect gets messed up whenever you have different Clipping Planes values, so I guess the shader is a bit finicky. :confused:
     
  7. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    Well that makes sense, the depth value 0 to 1 tells you how far between the near and far plane you are where 0 is the near plane and 1 is the far plane.
     
    pixpusher2 likes this.
  8. JamhammerDev

    JamhammerDev

    Joined:
    Jul 11, 2015
    Posts:
    28
    It's been a number of years, but would anyone have any ideas or insight into this? Trying to wrap my head around shaderforge and the above comments is leading me nowhere!
     
  9. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    Sorry for the non-answer, but Shaderforge isn't supported in Unity 2017 or later, so you may want to consider switching to Amplify shader editor or the built-in shader graph.

    If you must have an answer, you may want to start your own thread to get new eyes on the question, or ask in the shader forge forums.
     
  10. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,933
    This 3-line code snippet seems the best start for dealing with these issues:

    https://forum.unity.com/threads/get...-the-orthographic-camera.601825/#post-4966334

    ... it essentially replaces LinearEyeDepth with a more intelligent decision based on the camera's current mode.

    It is not perfect - UnityEditor makes some guesses when converting to/from ortho camera that aren't always correct - but it's a good start and is easily tweakable.