SpiralCircus

I'm making use of the "Spine/Sprites/xxx" shader to allow for depth of field post-processing effects to work on my animated sprites.

I was wondering if you had a some info somewhere about how the "write to depth" is acheived such that it writes to the camera depth texture, while still showing the nice transparent smooth alpha sprite. Is it using replaement shaders to replace the in-built unity cameraDepthTexture shader?

Is it possible to leverage this in my own custom sprite shaders for use on regular sprites that aren't making use of SkeletonRenderer? I'd love some advice about this, since you've already solved a problem I've been struggling with for months, namely, how to render smooth transparent sprites while writing a rougher cutout to the camera depth texture.

TL/DR: How do i utilise the CameraDepthTexture replacement shader from Spine in my own custom shaders?
SpiralCircus
  • Postovi: 11

Harald

Have you tried creating a copy of the CameraDepthTexture shader and adding your required parts to it? Then you would need to call camera.RenderWithShader() with your respective shader.

At the end you could copy and adapt the part
SubShader {
Tags { "RenderType"="Sprite" }
to add your own custom type like
SubShader {
Tags { "RenderType"="MyCustomSprite" }
Be sure to have the corresponding line clip( alpha - _Cutoff ); in the fragment shader as well to get the cutout effect at the depth buffer. Also be sure to name the parameters like they are in your original shader.
Avatar
Harald

Harri
  • Postovi: 4101

SpiralCircus

Thanks for the info. I noticed that when I use one of the spine "Sprites/XXX" shaders, I can toggle on depth write and it writes to depth, without having to call
camera.RenderWithShader()
anywhere. This is the case even when i use the material on a simple sprite renderer with no spine components attached. Am I missing something? How is this acheived without the camera code in place?

Another thing I noticed when testing the above is that when depth write is toggled on, the sprite starts to look jagged again, following the depth alpha cutoff value, is this expected behaviour? To me it looks the same as simply changing the render type to "cutout" using the standard shader, but I thought the purpose of this replacement was to visually render the soft edges as with a transparent shader, but also to render the cutout sprite to the depth texture for screen-space post processing.

My apologies if these questions are a little uninformed, i'm very much not a graphics programmer. I'm fine with the csharp side of things but I'm not so great with shaders.
SpiralCircus
  • Postovi: 11

Harald

Have you tried enabling Write to Depth and setting Depth Alpha Cutoff to 0.0001? This results in nice blended results with no jagged borders (because the cutoff is set to "only discard when alpha <= 0.0001") while still rendering the whole sprite to the depth buffer:

WriteToDepthSettings.PNG

WriteToDepthHero.PNG
Magnified view of the Hero character. Enabled depth write provides the correct depth value for the camera blur effect.

---

[Edit:]
Note however that when you use a blur effect and have multiple sprites layered behind each other, then by design you will have problems in non-cut-off areaswhen setting the cutoff threshold to 0.0001 - then a nicely alpha-blended 95% transparent black pixel will receive 95% of the background color, and thus the background pixel will be perfectly sharp (non-blurred) when the character is in focus, where it should be blurry instead.

WriteToDepthHeroBlur.PNG
Some background pixels around the border wrote to character's depth since they were not discarded at 5% opacity - hence they are not blurry but as sharp as the character.

In this case you cannot handle this in a single render pass - that's where you need the two different alpha cutoff thresholds:
1) one that is low enough to not discard the transparent pixel in the first pass, and then
2) another one at e.g. 0.5 that blurs everything that is mostly transparent and therefore shall count as background.
This case is where the camera.RenderWithShader() replacement shaders come in handy, since they can render another pass just to write different depth values.
Nemaš dopuštenje za pregledavanje privit(a)ka dodan(og)ih postu.
Avatar
Harald

Harri
  • Postovi: 4101

SpiralCircus

Thanksyou for the detailed reply Harald. I'm the lone programmer on our team so I frequenctly have to bounce between areas of focus for particular deadlines, which means sometimes I can't quickly go back and test your advice, but I'll let you know how I get on when i get back to that problem. Really appreciate you taking the time to answer.
SpiralCircus
  • Postovi: 11

Harald

You're welcome, hope it helps! No need to hurry at all.
Avatar
Harald

Harri
  • Postovi: 4101

csumsky3

Hello! Glad I found this thread :) Wanting to do the same thing - get depth info for our spine objects so that we can use depth of field effects. However, when I try toggling on "Write to Depth" on a Spine/Sprite/Unlit shader, I get the following weirdness:

https://www.dropbox.com/s/hq4putsjdionnih/depth%20write%20issue.gif?dl=0

Is it because all of the skeleton's sprites are in the same z-space, so they're just all clipping? Maybe that's not the case, just a hunch! Happy to provide more details, but figured I'd just start there. Thanks!
Avatar
csumsky3
  • Postovi: 30

Harald

Hello! :)
You can set Z Spacing in the inspector of the SkeletonAnimation component, under the Advanced section.
Avatar
Harald

Harri
  • Postovi: 4101

csumsky3

:bigeyed: just like that huh! Thanks!
Avatar
csumsky3
  • Postovi: 30

Harald

You're welcome 8)
Avatar
Harald

Harri
  • Postovi: 4101

Bekko

hey , )

is it possible to add " Write to Depth" to the skeleton shader ?
Bekko
  • Postovi: 32

Harald

It is possible, however the non-sprite shaders are kept simple on purpose - if we add too many things we end up at the Spine/Sprite/ shaders.
Is there a reason you don't want to use any of the Spine/Sprite/ shaders which provide this?
Avatar
Harald

Harri
  • Postovi: 4101

Bekko

hey @Harald

yes, the reason was, that my spine is rotating if the game object was > to an angle, but using the shader pixel vertex was strange,
skeleton shader worked perfectly but not good with the unity depth of field.. well

I was using

"transform.localEulerAngles = new Vector3(0, 180, 0);" to make a mirror,

but I thing I fix it using :

transform.localScale = new Vector3(-1, 1, 1);

sorry, thx
Bekko
  • Postovi: 32

Harald

Bekko je napisao/la:yes, the reason was, that my spine is rotating if the game object was > to an angle, but using the shader pixel vertex was strange
I fear I don't quite understand the above sentence.

Anyway, you could copy the existing Spine-SkeletonLit.shader shader file and modify the lines
// change this line to give it a new unique name: Shader "Spine/Skeleton Lit" {
// e.g. to this name:
Shader "Spine/Skeleton Lit Depth Write" {
and
either
  1. // change ZWrite Off to
    ZWrite On
    or
  2. // below [Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Compare", Float) = 0.0 // Disabled stencil test by default
    // add the line:
    _ZWrite ("Depth Write", Float) = 1.0

    // and change ZWrite Off to
    ZWrite [_ZWrite]

Then you can assign your new Spine/Skeleton Lit Depth Write shader as usual.
Avatar
Harald

Harri
  • Postovi: 4101

Bekko

thx
Bekko
  • Postovi: 32

xetaichohangpq

Unity 5 Sprite Shader with Depth Writing
gistfile1.txt
Shader "Sprites/DefaultWithDepth"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
_Color ("Tint", Color) = (1,1,1,1)
[MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
}

SubShader
{
Tags
{
"Queue"="AlphaTest"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}

Cull Off
Lighting Off
Blend One OneMinusSrcAlpha

Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ PIXELSNAP_ON
#include "UnityCG.cginc"

struct appdata_t
{
float4 vertex : POSITION;
float4 color : COLOR;
float2 texcoord : TEXCOORD0;
};

struct v2f
{
float4 vertex : SV_POSITION;
fixed4 color : COLOR;
half2 texcoord : TEXCOORD0;
};

fixed4 _Color;

v2f vert(appdata_t IN)
{
v2f OUT;
OUT.vertex = mul(UNITY_MATRIX_MVP, IN.vertex);
OUT.texcoord = IN.texcoord;
OUT.color = IN.color * _Color;
#ifdef PIXELSNAP_ON
OUT.vertex = UnityPixelSnap (OUT.vertex);
#endif

return OUT;
}

sampler2D _MainTex;

fixed4 frag(v2f IN) : SV_Target
{
fixed4 c = tex2D(_MainTex, IN.texcoord) * IN.color;
c.rgb *= c.a;
return c;
}
ENDCG
}

UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"
}
}
https://tktech.vn/ampe-kim/
xetaichohangpq
  • Postovi: 1

Harald

Thanks for sharing your code. Please note that
[code][/code]
tags can be used to format code nicely.
Avatar
Harald

Harri
  • Postovi: 4101

AlejMC

Hello! Had a question as it's not really clear for me just yet...
To render to the _CameraDepthTexture (where currently all "ShadowCaster pass" enabled Opaque and AlphaTest shaders are drawn) I put this Camera.RenderWithShader exactly where? on PreRender() of a Camera component script callback?

Looking through the files there's this:

Shader "Hidden/Sprite-CameraDepthTexture" {
// Use this shader to render a Depth texture for a camera with soft edged Sprites (using camera.RenderWithShader with replacement tag "RenderType")
// Note the depth is encoded into the pixels RGB not the full RGBA (alpha is needed for blending)
Which I can use as a starting point and not as is since I would rather have the Depth be just default grayscale depth (i.e. no RGB encoding) and clip the pixels with a custom shader but I haven't found a clear rule of thumb way to inject the spine objects into the currently ongoing _CameraDepthTexture target.

Two ways to go about it:
  • Duplicate the spine characters (or set a double material on their mesh renderers, one with an alpha test render queue and the other with the normal alpha blended transparent queue values). Cumbersome.
  • Camera.RenderWithShader with the proper tags (but not quite clear on the instructions)
AlejMC
  • Postovi: 1

Harald

If you haven't already, you might want to check out the following Unity documentation pages:
https://docs.unity3d.com/Manual/SL-ShaderReplacement.html
https://docs.unity3d.com/Manual/SL-CameraDepthTexture.html
Please note that IIRC only the built-in render pipeline (so not Universal Render Pipeline) supports replacement shaders.
Avatar
Harald

Harri
  • Postovi: 4101


Natrag na Unity