Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Why are there helper functions that are non existent in the unity docs?

Discussion in 'Shaders' started by TheCelt, Sep 2, 2019.

  1. TheCelt

    TheCelt

    Joined:
    Feb 27, 2013
    Posts:
    741
    I am currently trying to work out how to use depth textures but was hitting a road block.

    I ended up searching the forums to see example code for how people do it. And see people using functions that i had no idea even existed and the docs don't even mention.

    For example i am doing this in my frag shader:

    Code (CSharp):
    1.             // depthSample at screen position
    2.             float4 depthSample = SAMPLE_DEPTH_TEXTURE_PROJ(_DepthTexture,IN.screenPos);
    3.             // depth from 0 to 1
    4.             float depth = LinearEyeDepth(depthSample);
    But is this the right way to do it? I've seen other approaches as well.

    SAMPLE_DEPTH_TEXTURE_PROJ is no where to be seen in the documentation. Is this deprecated ? Does it work on all platforms... i have no idea....

    I'm using a surface shader if that matters here.

    Is this the correct approach ? I am doing depth texture sampling for ocean rendering. If this is not the correct way - some guidance would be welcome.
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    That’s a perfectly fine way of doing it. In fact the use of that macro (along with the UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);) was added to Unity shaders in part to help support more platforms. Specifically it helps for different VR modes which defines and accesses the depth texture in different ways.

    Why are they not in the documentation? Because a lot of stuff isn’t in the documentation. The changes to the code has far and away outstripped Unity’s ability to document, and things keep changing so a few times by the time documentation ends up getting updated it’s already outdated.

    Really, the only way to know what’s actually available is to read through the shader files yourself. There’s a lot of helper functions completely missed in the documentation, and a bunch of functions you might expect to exist that don’t.
    https://github.com/TwoTailsGames/Unity-Built-in-Shaders/blob/master/CGIncludes/UnityCG.cginc
    https://github.com/TwoTailsGames/Unity-Built-in-Shaders/blob/master/CGIncludes/HLSLSupport.cginc
     
  3. TheCelt

    TheCelt

    Joined:
    Feb 27, 2013
    Posts:
    741
    Thanks for the reply, I still have a few more things i am not understanding from the results i am getting perhaps you can see where i might have gone wrong.

    When i compare the depth differences between my frag's COMPUTE_EYEDEPTH and the depth texture LinearEyeDepth() the values don't seem to match what my math is doing.

    This is what i have:

    Relevant Vertex code:
    Code (CSharp):
    1. o.screenPos = ComputeScreenPos(UnityObjectToClipPos(v.vertex));
    2. COMPUTE_EYEDEPTH(o.screenPos.z);
    Relevant Frag code:
    Code (CSharp):
    1.  
    2.             float textureDepth = SAMPLE_DEPTH_TEXTURE_PROJ(_DepthTexture, IN.screenPos);
    3.          
    4.             // will this give approximate world units distance from the camera ???
    5.             float depthDifference = LinearEyeDepth(textureDepth) - IN.screenPos.z;
    6.  
    7.             // clamp difference in distance to maximum of 50 units
    8.             depthDifference = max(depthDifference,_MaxDepthVisibility);
    9.  
    10.             //at 50 units deep opacity should == 0
    11.             //_MaxDepthVisibility = 50
    12.             float depth = 1 - ( depthDifference / _MaxDepthVisibility);
    13.  
    14.             o.Albedo = float3(1,1,1) * _Color;
    15.             o.Alpha =  depth;
    From what i assumed, this should become more opaque the deep the object is under the water surface up to a maximum of 50 units - at which point its always 0 on the alpha.

    Yet for me, the whole water surface is transparent so i seem to be getting a final depth of 1.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Everything looks fine from that code, though you mentioned you’re using a Surface Shader. The screenPos variable name is a special variable that the Surface Shader handles. It’s likely ignoring whatever values you’re setting in your custom vertex function, and I don’t believe the built in screenPos calculates the eye depth.

    Try renaming it “screenPosition”.
     
  5. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,539
    Another issue is that with shaders there isn't a reliable way to produce automated documentation structures that can then simply be run through by someone and kept maintained reasonably, unlike with the C# stuff. It's a more involved documentation process that also serves a much smaller userbase compared to the C# side, a userbase that usually will have to learn to be savvy enough to dig through shader includes anyway.
     
  6. TheCelt

    TheCelt

    Joined:
    Feb 27, 2013
    Posts:
    741
    Thanks for the suggestion. I changed it to this:


    Code (CSharp):
    1.         void vert (inout appdata v, out Input o)
    2.         {
    3.             UNITY_INITIALIZE_OUTPUT(Input, o);
    4.             o.screenPosition = ComputeScreenPos(UnityObjectToClipPos(v.vertex));
    5.      
    6.             //o.screenPosition.z = -UnityObjectToViewPos( v.vertex ).z
    7.             COMPUTE_EYEDEPTH(o.screenPosition.z);
    8.         }
    9.  
    10.         void surf (Input IN, inout SurfaceOutputStandard o)
    11.         {
    12.             float textureDepth = SAMPLE_DEPTH_TEXTURE_PROJ(_DepthTexture, IN.screenPosition);
    13.      
    14.             // depth of texture sample from water fragment in world units [approximate]
    15.             float depthDifference = LinearEyeDepth(textureDepth) - IN.screenPosition.z;
    16.  
    17.             // clamp difference in distance to maximum of 50 units
    18.             depthDifference = clamp(depthDifference,0,_MaxDepthVisibility);
    19.  
    20.             //at 50 units deep opacity should == 1
    21.             //_MaxDepthVisibility = 50
    22.             float depth = saturate(depthDifference / _MaxDepthVisibility);
    23.  
    24.             o.Albedo = float3(1,1,1) * _Color;
    25.             o.Alpha =  depth;
    26.         }
    27.  
    For me i'm just getting a depth of 1 no matter what. That seems to imply to me that the depth difference is always 0......I must be missing something there?

    Here is what it looks like in the engine:



    Some extra info :
    Code (csharp):
    1.  
    2.         #pragma surface surf Standard vertex:vert alpha:blend
    3.         #pragma target 3.0
    4.  
    And i have:

    Code (csharp):
    1. Tags { "Queue"="Transparent" "RenderType"="Transparent" }
    With these keywords:
    Code (csharp):
    1.  
    2.         LOD 200
    3.         Blend SrcAlpha OneMinusSrcAlpha
    4.         ZWrite Off
    5.  
    I must still be missing something because its not working still.

    I also have checked that the depth texture is enabled:
    upload_2019-9-3_21-1-30.png
     
    Last edited: Sep 3, 2019
  7. TheCelt

    TheCelt

    Joined:
    Feb 27, 2013
    Posts:
    741
    I have since solved the problem :) Turns out i was overwriting _DepthTexture with my own custom texture when i was debugging and forgot i had done that.
     
    bgolus likes this.