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

Question Prevent self transparency in vertex displacement shader

Discussion in 'Universal Render Pipeline' started by EdEddnEddy, Jan 8, 2021.

  1. EdEddnEddy

    EdEddnEddy

    Joined:
    Sep 15, 2015
    Posts:
    16
    I'm writing a transparent shader with vertex displacement. I would like to prevent self transparency so that the displaced geometry would not be visible when it "dips below" the mesh once its displaced, but other objects behind it would be visible.

    Ideal situation for the effect:
    upload_2021-1-8_21-38-22.png

    Issue with "heavier" objects:
    upload_2021-1-8_21-38-30.png

    Project configuration:
    • Unity 2019.4.14f1
    • Universal RP 7.3.1

    Shader code:
    Code (csharp):
    1. Shader "Space Grid"
    2. {
    3.     Properties
    4.     {
    5.         _DisplacementSmoothness("Displacement Smoothness", float) = 5
    6.  
    7.         _GridThickness("Grid Thickness", Range(0, 10)) = 0.5
    8.         _GridTiling("Grid Tiling", Vector) = (16, 16, 0, 0)
    9.         _GridOffset("Grid Offset", Vector) = (0, 0, 0, 0)
    10.  
    11.         [HDR] _BackgroundColor("Background Color", Color) = (0, 0, 0, 0.5)
    12.         [HDR] _GridColor("Color", Color) = (1, 1, 1, 1)
    13.  
    14.     }
    15.     SubShader
    16.     {
    17.         Tags
    18.         {
    19.             "Queue" = "Transparent"
    20.             "RenderPipeline" = "UniversalPipeline"
    21.         }
    22.  
    23.         HLSLINCLUDE
    24.         #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    25.  
    26.         CBUFFER_START(UnityPerMaterial)
    27.  
    28.         // Constants.
    29.         static const int MAX_POINT_COUNT = 256;
    30.  
    31.         // Gird parameters.
    32.         uniform float _GridThickness;
    33.  
    34.         uniform float2 _GridTiling;
    35.         uniform float2 _GridOffset;
    36.         uniform float4 _BackgroundColor;
    37.         uniform float4 _GridColor;
    38.  
    39.         // Displacement parameters.
    40.         uniform float _DisplacementSmoothness;
    41.  
    42.         // Point parameters.
    43.         uniform int _PointCount;
    44.         uniform float3 _PointPositions[MAX_POINT_COUNT];
    45.         uniform float _PointStrengths[MAX_POINT_COUNT];
    46.         uniform float _PointSizes[MAX_POINT_COUNT];
    47.  
    48.         CBUFFER_END
    49.         ENDHLSL
    50.  
    51.         Pass
    52.         {
    53.             Blend SrcAlpha OneMinusSrcAlpha
    54.             ZWrite Off
    55.             HLSLPROGRAM
    56.             #pragma vertex vert
    57.             #pragma fragment frag
    58.  
    59.             struct VertData
    60.             {
    61.                 float4 vertex : POSITION;
    62.                 float2 uv : TEXCOORD0;
    63.             };
    64.  
    65.             struct FragData
    66.             {
    67.                 float4 vertex : SV_POSITION;
    68.                 float2 uv : TEXCOORD0;
    69.             };
    70.  
    71.             float displace(
    72.                 const float2 world_position,
    73.                 const float2 point_position,
    74.                 const float point_strength,
    75.                 const float point_size
    76.             )
    77.             {
    78.                 const float displacement = smoothstep(
    79.                     point_size * (1 - _DisplacementSmoothness),
    80.                     point_size,
    81.                     distance(world_position, point_position)
    82.                 );
    83.  
    84.                 return (1.0 - displacement) * point_strength;
    85.             }
    86.  
    87.             float displace_all(const float2 world_position)
    88.             {
    89.                 float displacement = 0.0;
    90.                 for (int i = 0; i < _PointCount; i++)
    91.                 {
    92.                     displacement += displace(
    93.                         world_position,
    94.                         _PointPositions[i].xz,
    95.                         _PointStrengths[i],
    96.                         _PointSizes[i]
    97.                     );
    98.                 }
    99.  
    100.                 return displacement;
    101.             }
    102.  
    103.             float2 tiling_and_offset(const float2 uv)
    104.             {
    105.                 return uv * _GridTiling + _GridOffset;
    106.             }
    107.  
    108.             // See: https://gamedev.stackexchange.com/questions/141916/antialiasing-shader-grid-lines
    109.             // Alternatively see: https://iquilezles.org/www/articles/filterableprocedurals/filterableprocedurals.htm
    110.             float filtered_grid(const float2 uv)
    111.             {
    112.                 const float2 wrapped = frac(uv) - 0.5f;
    113.                 const float2 range = abs(wrapped);
    114.  
    115.                 const float4 deltas = float4(ddx(uv), ddy(uv));
    116.                 const float2 speeds = sqrt(
    117.                     float2(
    118.                         dot(deltas.xz, deltas.xz),
    119.                         dot(deltas.yw, deltas.yw)
    120.                     )
    121.                 );
    122.  
    123.                 const float2 pixel_range = range / speeds;
    124.  
    125.                 return saturate(min(pixel_range.x, pixel_range.y) - _GridThickness);
    126.             }
    127.  
    128.             FragData vert(const VertData data)
    129.             {
    130.                 FragData frag_data;
    131.  
    132.                 const float3 world_position = TransformObjectToWorld(data.vertex);
    133.                 float3 object_position = data.vertex;
    134.  
    135.                 object_position.y -= displace_all(world_position.xz);
    136.  
    137.                 frag_data.vertex = TransformObjectToHClip(object_position);
    138.                 frag_data.uv = tiling_and_offset(data.uv);
    139.  
    140.                 return frag_data;
    141.             }
    142.  
    143.             float4 frag(const FragData data) : SV_Target
    144.             {
    145.                 return lerp(_GridColor, _BackgroundColor, filtered_grid(data.uv));
    146.             }
    147.             ENDHLSL
    148.         }
    149.     }
    150. }
    I've tried the following approaches:
    Is this currently possible in URP? If so, how could I implement this with given my current setup?