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:
Shader "Custom/Sprite(Unit)"
{
Properties
{
_MainTex ("Main Texture", 2D) = "white" {}
_Color ("Color", Color) = (1,1,1,1)
PixelSnap ("Pixel snap", Float) = 0
_AlphaTex ("External Alpha", 2D) = "white" {}
_EnableExternalAlpha ("Enable External Alpha", Float) = 0
_ZWrite ("Depth Write", Float) = 0.0
_Cutoff ("Depth alpha cutoff", Range(0,1)) = 0.0
_ShadowAlphaCutoff ("Shadow alpha cutoff", Range(0,1)) = 0.3
_CustomRenderQueue ("Custom Render Queue", Float) = 0.0
_OverlayColor ("Overlay Color", Color) = (0,0,0,0)
_Hue("Hue", Range(-0.5,0.5)) = 0.0
_Saturation("Saturation", Range(0,2)) = 1.0
_Brightness("Brightness", Range(0,2)) = 1.0
_BlendTex ("Blend Texture", 2D) = "white" {}
_BlendAmount ("Blend", Range(0,1)) = 0.0
_EmissionMap("Emission Map", 2D) = "black" {}
[HDR] _EmissionColor("Emission Color", Color) = (0, 0, 0)
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
[HideInInspector] _RenderQueue ("__queue", Float) = 0.0
[HideInInspector] _Cull ("__cull", Float) = 0.0
_RenderQueue("Render Queue", Float) = 0.0
_Matrix1("matrix", vector) = (1,1,1,1)
_Matrix2("matrix", vector) = (1,1,1,1)
_Matrix3("matrix", vector) = (1,1,1,1)
// Custom
[Toggle] _Frozen ("Frozen Status", Int) = 0
_OutlineMode ("Outline Mode", Int) = 0
_AllianceColor ("Alliance Color", Color) = (0, 0, 0, 1)
}
SubShader
{
Tags
{
"Queue" = "Transparent"
"RenderType" = "Sprite"
"AlphaDepth" = "False"
"CanUseSpriteAtlas" = "True"
"IgnoreProjector" = "True"
}
LOD 100
// Main Pass
Pass
{
Blend[_SrcBlend][_DstBlend]
Lighting Off
ZWrite[_ZWrite]
ZTest LEqual
Cull[_Cull]
Lighting Off
// Write to stencil
Stencil
{
Ref 4
Comp always
Pass replace
ZFail keep
Fail replace
}
CGPROGRAM
#pragma shader_feature _ _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON _ADDITIVEBLEND _ADDITIVEBLEND_SOFT _MULTIPLYBLEND _MULTIPLYBLEND_X2
#pragma shader_feature _ALPHA_CLIP
#pragma shader_feature _TEXTURE_BLEND
#pragma shader_feature _COLOR_ADJUST
#pragma shader_feature _FOG
#pragma fragmentoption ARB_precision_hint_fastest
#pragma multi_compile_fog
#pragma multi_compile_instancing
#pragma multi_compile _ PIXELSNAP_ON
#pragma multi_compile _ ETC1_EXTERNAL_ALPHA
#pragma vertex vert
#pragma fragment frag
#include "../Shaders/shaders_includes/SpriteShaders/CGIncludes/SpriteUnlit.cginc"
ENDCG
}
// Shadow
Pass
{
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
Offset 1, 1
Fog { Mode Off }
ZWrite On
ZTest LEqual
Cull Off
Lighting Off
CGPROGRAM
#pragma fragmentoption ARB_precision_hint_fastest
#pragma multi_compile_shadowcaster
#pragma multi_compile_instancing
#pragma multi_compile _ PIXELSNAP_ON
#pragma multi_compile _ ETC1_EXTERNAL_ALPHA
#pragma vertex vert
#pragma fragment frag
#include "../Shaders/shaders_includes/SpriteShaders/CGIncludes/SpriteShadows.cginc"
ENDCG
}
// X-Ray Shader Pass
Pass
{
Tags{
"Queue" = "Transparent"
"AlphaDepth" = "True"
}
Cull Off
ZWrite off
ZTest always
Stencil
{
Ref 4
Comp notequal
Pass keep
Fail keep
}
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "../Shaders/shaders_includes/SpriteShaders/CGIncludes/ShaderShared.cginc"
float4 _MainTex_TexelSize;
float4 _AllianceColor;
int _OutlineMode;
struct v_in {
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
struct v_out {
float4 pos : SV_POSITION;
float2 texcoord : TEXCOORD0;
fixed4 color : COLOR;
};
v_out vert(v_in input) {
v_out output;
output.pos = calculateLocalPos(input.vertex);
output.texcoord = calculateTextureCoord(input.texcoord);
return output;
}
float4 frag(v_out input) : SV_TARGET
{
// Dead unit, then skips this pass
if (_OutlineMode == 2)
discard;
fixed4 textureColor = calculateTexturePixel(input.texcoord.xy);
ALPHA_CLIP_COLOR(texureColor, input.color);
if (textureColor.a < 0.1f)
discard;
if (_OutlineMode == 0) {
if (textureColor.a < 0.2f)
discard;
return _AllianceColor;
}
// Outline only
if (textureColor.a != 0) {
// Get the neighbouring four pixels.
fixed4 pixelUp = tex2D(_MainTex, input.texcoord.xy + float2(0, _MainTex_TexelSize.y));
fixed4 pixelDown = tex2D(_MainTex, input.texcoord.xy - float2(0, _MainTex_TexelSize.y));
fixed4 pixelRight = tex2D(_MainTex, input.texcoord.xy + float2(_MainTex_TexelSize.x, 0));
fixed4 pixelLeft = tex2D(_MainTex, input.texcoord.xy - float2(_MainTex_TexelSize.x, 0));
// If one of the neighbouring pixels is invisible, render outline.
if (pixelUp.a * pixelDown.a * pixelRight.a * pixelLeft.a == 0) {
textureColor.rgba = fixed4(1, 1, 1, textureColor.a) * _AllianceColor;
}
else {
discard;
}
}
return textureColor;
}
ENDCG
}
}
CustomEditor "SpriteShaderGUI"
}