Search Unity

Question URP Custom Sprite Shader

Discussion in 'Universal Render Pipeline' started by anthonytrianh, Aug 4, 2020.

  1. anthonytrianh

    anthonytrianh

    Joined:
    Dec 7, 2018
    Posts:
    6
    I'm expermenting with Unity 2020.1's URP to see if it's worth upgrading my project but so far I have had some difficulties trying to get my custom shader to work with the URP.


    This is the shader effect I have, where each unit (2D SpriteRenderers) are colored silhouettes when occluded by objects/3D meshes, colors based on whichever alliance they belong to. The shader itself is a customized version of Unity's Sprite Shader, I wrote an extra pass with custom fields to create the X-Ray effect (with a lot of tinkering around with ZDepth and Stencil to get this to work). The colors are set during the initialization state of the game and can be changed via events.

    As far as I know, my shader doesn't work in URP since it uses forward rather than deferred rendering. So my only option was to follow this tutorial by Brackey's:

    In order to get this:

    But this doesn't really cut it for me as it simply uses a shared shader and renders all occluded parts of a sprite using said shader, which doesn't allow for any customization whatsoever. The only way I could think of to somehow achieve the effect of my custom shader is to somehow have the shader I made for URP take in a variable of the current object being rendered as the alliance color to and render the silhouette with it. But I don't think there is anyway for me to do this.

    If anyone has any ideas, it'll be much appreciated.

    Here's the custom shader if anyone's interested:
    Code (CSharp):
    1. Shader "Custom/Sprite(Unit)"
    2. {
    3.     Properties
    4.     {
    5.         _MainTex ("Main Texture", 2D) = "white" {}
    6.         _Color ("Color", Color) = (1,1,1,1)
    7.      
    8.         PixelSnap ("Pixel snap", Float) = 0
    9.         _AlphaTex ("External Alpha", 2D) = "white" {}
    10.         _EnableExternalAlpha ("Enable External Alpha", Float) = 0
    11.      
    12.         _ZWrite ("Depth Write", Float) = 0.0
    13.         _Cutoff ("Depth alpha cutoff", Range(0,1)) = 0.0
    14.         _ShadowAlphaCutoff ("Shadow alpha cutoff", Range(0,1)) = 0.3
    15.         _CustomRenderQueue ("Custom Render Queue", Float) = 0.0
    16.      
    17.         _OverlayColor ("Overlay Color", Color) = (0,0,0,0)
    18.         _Hue("Hue", Range(-0.5,0.5)) = 0.0
    19.         _Saturation("Saturation", Range(0,2)) = 1.0  
    20.         _Brightness("Brightness", Range(0,2)) = 1.0  
    21.      
    22.         _BlendTex ("Blend Texture", 2D) = "white" {}
    23.         _BlendAmount ("Blend", Range(0,1)) = 0.0
    24.      
    25.         _EmissionMap("Emission Map", 2D) = "black" {}
    26.         [HDR] _EmissionColor("Emission Color", Color) = (0, 0, 0)
    27.  
    28.         [HideInInspector] _SrcBlend ("__src", Float) = 1.0
    29.         [HideInInspector] _DstBlend ("__dst", Float) = 0.0
    30.         [HideInInspector] _RenderQueue ("__queue", Float) = 0.0
    31.         [HideInInspector] _Cull ("__cull", Float) = 0.0
    32.  
    33.         _RenderQueue("Render Queue", Float) = 0.0
    34.  
    35.         _Matrix1("matrix", vector) = (1,1,1,1)
    36.         _Matrix2("matrix", vector) = (1,1,1,1)
    37.         _Matrix3("matrix", vector) = (1,1,1,1)
    38.  
    39.         // Custom
    40.         [Toggle] _Frozen ("Frozen Status", Int) = 0
    41.  
    42.  
    43.         _OutlineMode ("Outline Mode", Int) = 0
    44.         _AllianceColor ("Alliance Color", Color) = (0, 0, 0, 1)
    45.     }
    46.  
    47.  
    48.     SubShader
    49.     {
    50.         Tags
    51.         {
    52.             "Queue" = "Transparent"
    53.             "RenderType" = "Sprite"
    54.             "AlphaDepth" = "False"
    55.             "CanUseSpriteAtlas" = "True"
    56.             "IgnoreProjector" = "True"
    57.         }
    58.         LOD 100
    59.  
    60.         // Main Pass
    61.         Pass
    62.         {
    63.             Blend[_SrcBlend][_DstBlend]
    64.             Lighting Off
    65.             ZWrite[_ZWrite]
    66.             ZTest LEqual
    67.             Cull[_Cull]
    68.             Lighting Off
    69.  
    70.             // Write to stencil
    71.             Stencil
    72.             {
    73.                 Ref 4
    74.                 Comp always
    75.                 Pass replace
    76.                 ZFail keep
    77.                 Fail replace
    78.             }
    79.  
    80.             CGPROGRAM
    81.                 #pragma shader_feature _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ADDITIVEBLEND _ADDITIVEBLEND_SOFT _MULTIPLYBLEND _MULTIPLYBLEND_X2
    82.                 #pragma shader_feature _ALPHA_CLIP
    83.                 #pragma shader_feature _TEXTURE_BLEND
    84.                 #pragma shader_feature _COLOR_ADJUST
    85.                 #pragma shader_feature _FOG
    86.  
    87.                 #pragma fragmentoption ARB_precision_hint_fastest
    88.                 #pragma multi_compile_fog
    89.                 #pragma multi_compile_instancing
    90.                 #pragma multi_compile _ PIXELSNAP_ON
    91.                 #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
    92.  
    93.                 #pragma vertex vert
    94.                 #pragma fragment frag
    95.  
    96.                 #include "../Shaders/shaders_includes/SpriteShaders/CGIncludes/SpriteUnlit.cginc"
    97.             ENDCG
    98.         }
    99.          
    100.         // Shadow
    101.         Pass
    102.         {
    103.             Name "ShadowCaster"
    104.             Tags { "LightMode" = "ShadowCaster" }
    105.             Offset 1, 1
    106.  
    107.             Fog { Mode Off }
    108.             ZWrite On
    109.             ZTest LEqual
    110.             Cull Off
    111.             Lighting Off
    112.  
    113.             CGPROGRAM
    114.                 #pragma fragmentoption ARB_precision_hint_fastest
    115.                 #pragma multi_compile_shadowcaster
    116.                 #pragma multi_compile_instancing
    117.                 #pragma multi_compile _ PIXELSNAP_ON
    118.                 #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
    119.  
    120.                 #pragma vertex vert
    121.                 #pragma fragment frag
    122.  
    123.                 #include "../Shaders/shaders_includes/SpriteShaders/CGIncludes/SpriteShadows.cginc"
    124.  
    125.             ENDCG
    126.         }
    127.      
    128.         // X-Ray Shader Pass
    129.         Pass
    130.         {
    131.             Tags{
    132.                  "Queue" = "Transparent"
    133.                  "AlphaDepth" = "True"
    134.             }
    135.  
    136.             Cull Off
    137.             ZWrite off
    138.             ZTest always
    139.             Stencil
    140.             {
    141.                 Ref 4
    142.                 Comp notequal
    143.                 Pass keep
    144.                 Fail keep
    145.             }
    146.             Blend SrcAlpha OneMinusSrcAlpha
    147.          
    148.          
    149.             CGPROGRAM
    150.             #pragma vertex vert
    151.             #pragma fragment frag
    152.             #include "../Shaders/shaders_includes/SpriteShaders/CGIncludes/ShaderShared.cginc"
    153.  
    154.             float4 _MainTex_TexelSize;
    155.             float4 _AllianceColor;
    156.             int _OutlineMode;
    157.  
    158.             struct v_in {
    159.                 float4 vertex : POSITION;
    160.                 float4 texcoord : TEXCOORD0;
    161.             };
    162.  
    163.             struct v_out {
    164.                 float4 pos : SV_POSITION;
    165.                 float2 texcoord : TEXCOORD0;
    166.                 fixed4 color : COLOR;
    167.             };
    168.  
    169.             v_out vert(v_in input) {
    170.                 v_out output;
    171.  
    172.                 output.pos = calculateLocalPos(input.vertex);
    173.                 output.texcoord = calculateTextureCoord(input.texcoord);
    174.  
    175.                 return output;
    176.             }
    177.  
    178.             float4 frag(v_out input) : SV_TARGET
    179.             {
    180.                 // Dead unit, then skips this pass
    181.                 if (_OutlineMode == 2)
    182.                     discard;
    183.  
    184.                 fixed4 textureColor = calculateTexturePixel(input.texcoord.xy);
    185.                 ALPHA_CLIP_COLOR(texureColor, input.color);
    186.  
    187.                 if (textureColor.a < 0.1f)
    188.                     discard;
    189.  
    190.                 if (_OutlineMode == 0) {
    191.                     if (textureColor.a < 0.2f)
    192.                         discard;
    193.                     return _AllianceColor;
    194.                 }
    195.  
    196.                 // Outline only
    197.                 if (textureColor.a != 0) {
    198.                     // Get the neighbouring four pixels.
    199.                     fixed4 pixelUp        =    tex2D(_MainTex, input.texcoord.xy + float2(0, _MainTex_TexelSize.y));
    200.                     fixed4 pixelDown    =    tex2D(_MainTex, input.texcoord.xy - float2(0, _MainTex_TexelSize.y));
    201.                     fixed4 pixelRight    =    tex2D(_MainTex, input.texcoord.xy + float2(_MainTex_TexelSize.x, 0));
    202.                     fixed4 pixelLeft    =    tex2D(_MainTex, input.texcoord.xy - float2(_MainTex_TexelSize.x, 0));
    203.  
    204.                     // If one of the neighbouring pixels is invisible, render outline.
    205.                     if (pixelUp.a * pixelDown.a * pixelRight.a * pixelLeft.a == 0) {
    206.                         textureColor.rgba = fixed4(1, 1, 1, textureColor.a) * _AllianceColor;
    207.                     }
    208.                     else {
    209.                         discard;
    210.                     }
    211.                 }
    212.  
    213.  
    214.                 return textureColor;
    215.             }
    216.  
    217.             ENDCG
    218.         }
    219.     }
    220.  
    221.     CustomEditor "SpriteShaderGUI"
    222. }
    223.  
     
  2. Simon_E_Sorensen

    Simon_E_Sorensen

    Unity Technologies

    Joined:
    Feb 4, 2020
    Posts:
    10
    Hi anthonytrianh,
    If I understand your problem correctly, you wish to be able to set, for instance, the player colors to different colors than the enemies when occluded?
    One solution could be to build on top of the RenderObjects/RenderObjectsPass code with a custom render pass and have multiple layers masks (Player1, Player2, Enemies etc.) which each have a a different color(or other properties) passed into an instance of the material you wish to use.
    For example like this:
    Unity_QV9AStrNkr.png