Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

HDRP CustomPass Shader - how to get the distance to camera?

Discussion in 'High Definition Render Pipeline' started by John_Leorid, Dec 20, 2020.

  1. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    624
    I want to see enemies through walls but only within a certain distance (10m).
    The outline shader from the example files seems to work fine, my only problem is the depth.
    The camera depth is wrong, because the objects I am rendering are actually behind other objects - so I need to get the actual distance to the camera somehow.. I've just no idea how to do so.

    upload_2020-12-20_16-33-42.png
    upload_2020-12-20_16-39-59.png

    This is my altered shader code:

    Code (CSharp):
    1. Shader "02_Selection/Fullscreen"
    2. {
    3.     properties
    4.     {
    5.         _SamplePrecision ("Sampling Precision", Range(1,3) ) = 1
    6.         _OutlineWidth ("Outline Width", Float ) = 5
    7.      
    8.         _InnerColor ("Inner Color", Color) = (1, 1, 0, 0.5)
    9.         _OuterColor( "Outer Color", Color ) = (1, 1, 0, 1)
    10.         _Texture ("Texture", 2D ) = "black" {}
    11.         _TextureSize("Texture Pixels Size", Vector) = (64,64,0,0)
    12.      
    13.         _BehindFactor("Behind Factor", Range(0,1)) = 0.2
    14.         _OnlyBehind("Only Behind", Range(0,1)) = 0.0
    15.         _Helper("Helper", Range(-1,1)) = 0.0
    16.  
    17.         _MaxDst("Max Distance", Float) = -1.0
    18.     }
    19.  
    20.     HLSLINCLUDE
    21.  
    22.     #pragma vertex Vert
    23.  
    24.     #pragma target 4.5
    25.     #pragma only_renderers d3d11 ps4 xboxone vulkan metal switch
    26.  
    27.     #include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/RenderPass/CustomPass/CustomPassCommon.hlsl"
    28.  
    29.     // The PositionInputs struct allow you to retrieve a lot of useful information for
    30.     // your fullScreenShader:
    31.     // struct PositionInputs
    32.     // {
    33.     //     float3 positionWS;  // World space position (could be camera-relative)
    34.     //     float2 positionNDC; // Normalized screen coordinates within the viewport    : [0, 1) (with the half-pixel offset)
    35.     //     uint2  positionSS;  // Screen space pixel coordinates                       : [0, NumPixels)
    36.     //     uint2  tileCoord;   // Screen tile coordinates                              : [0, NumTiles)
    37.     //     float  deviceDepth; // Depth from the depth buffer                          : [0, 1] (typically reversed)
    38.     //     float  linearDepth; // View space Z coordinate                              : [Near, Far]
    39.     // };
    40.  
    41.     // To sample custom buffers, you have access to these functions:
    42.     // But be careful, on most platforms you can't sample to the bound
    43.     // color buffer. It means that you
    44.     // can't use the SampleCustomColor when the pass color buffer is set to
    45.     // custom (and same for camera the buffer).
    46.     // float3 SampleCustomColor(float2 uv);
    47.     // float3 LoadCustomColor(uint2 pixelCoords);
    48.     // float LoadCustomDepth(uint2 pixelCoords);
    49.     // float SampleCustomDepth(float2 uv);
    50.  
    51.     // There are also a lot of utility function you can use inside Common.hlsl and
    52.     // Color.hlsl,
    53.     // you can check them out in the source code of the core SRP package.
    54.  
    55.     #define v2 1.41421
    56.     #define c45 0.707107
    57.     #define c225 0.9238795
    58.     #define s225 0.3826834
    59.  
    60.     #define MAXSAMPLES 16
    61.     static float2 offsets[MAXSAMPLES] = {
    62.         float2( 1, 0 ),
    63.         float2( -1, 0 ),
    64.         float2( 0, 1 ),
    65.         float2( 0, -1 ),
    66.      
    67.         float2( c45, c45 ),
    68.         float2( c45, -c45 ),
    69.         float2( -c45, c45 ),
    70.         float2( -c45, -c45 ),
    71.      
    72.         float2( c225, s225 ),
    73.         float2( c225, -s225 ),
    74.         float2( -c225, s225 ),
    75.         float2( -c225, -s225 ),
    76.         float2( s225, c225 ),
    77.         float2( s225, -c225 ),
    78.         float2( -s225, c225 ),
    79.         float2( -s225, -c225 )
    80.     };
    81.  
    82.     int _SamplePrecision;
    83.     float _OutlineWidth;
    84.  
    85.     float4 _InnerColor;
    86.     float4 _OuterColor;
    87.  
    88.     Texture2D _Texture;
    89.     float2 _TextureSize;
    90.  
    91.     float _BehindFactor;
    92.     float _OnlyBehind;
    93.     float _Helper;
    94.  
    95.     float _MaxDst;
    96.  
    97.     float4 FullScreenPass(Varyings varyings) : SV_Target
    98.     {
    99.         float depth = LoadCameraDepth(varyings.positionCS.xy);
    100.         PositionInputs posInput = GetPositionInput(varyings.positionCS.xy,
    101.             _ScreenSize.zw, depth, UNITY_MATRIX_I_VP, UNITY_MATRIX_V);
    102.         float3 viewDirection = GetWorldSpaceNormalizeViewDir(posInput.positionWS);
    103.      
    104.         float d = LoadCustomDepth(posInput.positionSS);
    105.         float db = LoadCameraDepth(posInput.positionSS);
    106.      
    107.         float alphaFactor = (db > d) ? _BehindFactor : 1 - _OnlyBehind;
    108.         float alphaFactorOutline = (db+_Helper>d)?_BehindFactor:1-_OnlyBehind;
    109.  
    110.         float4 c = LoadCustomColor(posInput.positionSS);
    111.  
    112.         float obj = c.a;
    113.      
    114.         uint offset = 5;
    115.      
    116.         int sampleCount = min( 2 * pow(2, _SamplePrecision ), MAXSAMPLES ) ;
    117.      
    118.         float4 outline = float4(0,0,0,0);
    119.      
    120.         float2 uvOffsetPerPixel = 1.0/_ScreenSize .xy;
    121.      
    122.         for (uint i=0 ; i<sampleCount ; ++i )
    123.         {
    124.             float2 norPos = posInput.positionNDC + uvOffsetPerPixel *
    125.                 _OutlineWidth * offsets[i];
    126.             outline =  max( SampleCustomColor(norPos), outline );
    127.         }
    128.  
    129.         float4 o = float4(0,0,0,0);
    130.      
    131.         float4 innerColor =
    132.             SAMPLE_TEXTURE2D( _Texture, s_trilinear_repeat_sampler,
    133.             posInput.positionSS / _TextureSize) * _InnerColor;
    134.      
    135.         float worldDepth = posInput.linearDepth;
    136.         float fadeMargin = abs(_MaxDst / 10) + 0.0001;
    137.         float startDstFade = _MaxDst - fadeMargin;
    138.         // from -infinite to startDstFade, distanceAlpha is 1
    139.         // lerp distanceAlpha drom startDstFade to _MaxDst, so it is 0 at _MaxDst
    140.         float distanceAlpha = saturate(1 - ((worldDepth - startDstFade) / fadeMargin));
    141.  
    142.         innerColor.a *= alphaFactor;
    143.         outline.a *= alphaFactorOutline;
    144.      
    145.         o = lerp(o, _OuterColor * float4(outline.rgb, 1), outline.a * distanceAlpha);
    146.      
    147.         o = lerp( o, innerColor * float4(c.rgb, 1), obj * distanceAlpha);
    148.      
    149.         return o;
    150.     }
    151.  
    152.     ENDHLSL
    153.  
    154.     SubShader
    155.     {
    156.         Pass
    157.         {
    158.             Name "Custom Pass 0"
    159.  
    160.             ZWrite Off
    161.             ZTest Always
    162.             Blend SrcAlpha OneMinusSrcAlpha
    163.             Cull Off
    164.  
    165.             HLSLPROGRAM
    166.                 #pragma fragment FullScreenPass
    167.             ENDHLSL
    168.         }
    169.     }
    170.     Fallback Off
    171. }
    172.  
     
  2. antoinel_unity

    antoinel_unity

    Unity Technologies

    Joined:
    Jan 7, 2019
    Posts:
    236
    Hello,

    In the HDRP Custom Passes repo, there is already something similar here:
    https://github.com/alelievr/HDRP-Cu...ction/Shaders/02_Selection_Objects.shader#L77

    As you can see, the distance to the camera can be checked with this:
    Code (CSharp):
    1. float distance = length(fragInputs.positionRWS);
    Note that this code returns the pixel distance to the camera and not the object distance to the camera.

    For the object distance you can do something like that:
    Code (CSharp):
    1. float distance = GetObjectToWorldMatrix()._m03_m13_m23;
    Distance to object may fail or return weird results if your objects are static because they can be combined when the game is built, thus changing the position of the original object to the average position of multiple objects.
     
    John_Leorid likes this.
  3. rikoo

    rikoo

    Joined:
    Nov 17, 2016
    Posts:
    11
    Hey everyone,

    I know it is kind of an old thread but does anyone have a solution that is not based on a shader?
    Like a way to filter while using custom pass would be great.

    Have a nice day
     
  4. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    624
    Not sure what exactly you mean, but the (default) Cusom Pass has a "LayerMask" property, so you can filter by layer.

     
  5. rikoo

    rikoo

    Joined:
    Nov 17, 2016
    Posts:
    11
    What I would like to do is to filtered the renderer list using the distance to camera. There it is in the shader but I would like to not render at all the one that are too far away.
    Any idea?
     
  6. fct509

    fct509

    Joined:
    Aug 15, 2018
    Posts:
    108
    If you can tag the enemies, then you can copy/render their depths to the custom buffer with the Renderers Custom Pass. With that, you can create your own custom pass that runs a shader that does a depth comparison between both buffers. Since, you only want to do this with enemies that are within a certain distance of the camera, you don't have to worry about the fact that the depth in the Custom Buffer will bottom out at the far clipping plane.