• RuntimesUnity
  • about transparency shader in Unity 6 with Spine 4.2.40 use built-in RP

suanLoBeach I achive the affect between two model, but not work for leaf in a same tree ( a same skeleton)
is it possibel to let transparent leaf occlusion each other in a same skeleton in unity ?

What do you mean you achieved the affect between two models? Can you show a screenshot of that? You will always have a cutout effect when writing to the z-buffer (or using the stencil buffer for masking). When not writing to the z-buffer, you will have half-transparent overlap, not masking each other.

    Harald I achive the affect between two model, but not work for leaf in a same tree ( a same skeleton)

    Perhaps I misunderstood what quality you want from your cutout effect. A perfect result like with normal transparent overlap is not possible, but you might be happy with a properly setup cutout shader already.

    Your original video in the first posting shows a cutout effect with no alpha threshold in place at all, or a very badly adjusted one. So you are likely just missing the alpha-based discard statement. You could have a look at e.g. the Spine/Skeleton Lit ZWrite shader where there is a _Cutoff property, or just use the Spine/Skeleton Lit ZWrite shader right away.

    Note that it's not a good idea to use the stencil buffer for depth-based masking, you should just write to the z buffer instead of the stencil buffer. The stencil buffer is normally used for masking and other non-depth-related shader things (shadow volumes, etc).

      Harald screenshot here

      Although it can't be fade in and out, more like cutout, but it's enough for me.

      well, I just wanna ask , Can the perfect feature be achived ? (only show the top transparent pixel)

        suanLoBeach Although it can't be fade in and out, more like cutout, but it's enough for me.

        Unfortunately I don't understand what you mean by that. Why can't you fade in or out? What is the setup in your screenshot, as it shows some semi-transparent parts and a write rectangle.

        Please always describe what you are trying to achieve and what you get instead in as much detail as possible. And when sharing screenshots, please note that we don't know the setup that has led to this screenshot, which objects are placed where (a scene view screenshot helps), which shaders are used where, etc.

        suanLoBeach well, I just wanna ask , Can the perfect feature be achived ? (only show the top transparent pixel)

        I just had a look at the Skeleton Lit ZWrite shader, it does not use a depth-pre-pass to ensure only the topmost triangles show through.

        So you could use the depth pre pass in your shader like from Spine/Outline/OutlineOnly-ZWrite. Add the following pass

        Pass
        {
        	Name "DepthOnly"
        
        	ZWrite On
        	ColorMask 0
        	Cull Off
        
        	CGPROGRAM
        	#pragma vertex DepthOnlyVertex
        	#pragma fragment DepthOnlyFragment
        	#include "CGIncludes/Spine-DepthOnlyPass.cginc"
        	ENDCG
        }

        before

        Pass {
            Name "Normal"

        Otherwise you would need to invert the draw order of your skeleton.

          Harald sorry to foget to post my code, I add these codes into spine/skeleton shader

          // code start
          Shader "Spine/Skeleton_custom" {
          Properties {
          _Cutoff ("Shadow alpha cutoff", Range(0,1)) = 0.1
          [NoScaleOffset] MainTex ("Main Texture", 2D) = "black" {}
          [Toggle(
          STRAIGHT_ALPHA_INPUT)] _StraightAlphaInput("Straight Alpha Texture", Int) = 0
          [HideInInspector] _StencilRef("Stencil Reference", Float) = 1.0
          [HideInInspector][Enum(UnityEngine.Rendering.CompareFunction)] _StencilComp("Stencil Comparison", Float) = 8 // Set to Always as default
          _AlphaClip ("Alpha Clip Threshold", Range(0.001,0.1)) = 0.01 // Alpha clipping threshold
          _AlphaFeathering ("Alpha Feathering", Range(0.001,0.05)) = 0.01 // Controls the feathering range

          	// Outline properties are drawn via custom editor.
          	[HideInInspector] _OutlineWidth("Outline Width", Range(0,8)) = 3.0
          	[HideInInspector][MaterialToggle(_USE_SCREENSPACE_OUTLINE_WIDTH)] _UseScreenSpaceOutlineWidth("Width in Screen Space", Float) = 0
          	[HideInInspector] _OutlineColor("Outline Color", Color) = (1,1,0,1)
          	[HideInInspector][MaterialToggle(_OUTLINE_FILL_INSIDE)]_Fill("Fill", Float) = 0
          	[HideInInspector] _OutlineReferenceTexWidth("Reference Texture Width", Int) = 1024
          	[HideInInspector] _ThresholdEnd("Outline Threshold", Range(0,1)) = 0.25
          	[HideInInspector] _OutlineSmoothness("Outline Smoothness", Range(0,1)) = 1.0
          	[HideInInspector][MaterialToggle(_USE8NEIGHBOURHOOD_ON)] _Use8Neighbourhood("Sample 8 Neighbours", Float) = 1
          	[HideInInspector] _OutlineOpaqueAlpha("Opaque Alpha", Range(0,1)) = 1.0
          	[HideInInspector] _OutlineMipLevel("Outline Mip Level", Range(0,3)) = 0
          }
          
          SubShader {
          	Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" "PreviewType"="Plane" }
          
          	Fog { Mode Off }
          	Cull Off
          	Lighting Off
          
          	Stencil {
          		Ref[_StencilRef]
          		Comp[_StencilComp]
          		Pass Keep
          	}
          
          	// Pass 1: Only writes depth, doesn't render color, but uses feathering effect
          	Pass {
          		Name "DepthOnly"
          		ZWrite On
          		ColorMask 0
          		
          		CGPROGRAM
          		#pragma vertex vert
          		#pragma fragment frag
          		#include "UnityCG.cginc"
          		#include "CGIncludes/Spine-Common.cginc"
          		sampler2D _MainTex;
          		float _AlphaClip;
          		float _AlphaFeathering;
          
          		struct VertexInput {
          			float4 vertex : POSITION;
          			float2 uv : TEXCOORD0;
          			float4 vertexColor : COLOR;
          		};
          
          		struct VertexOutput {
          			float4 pos : SV_POSITION;
          			float2 uv : TEXCOORD0;
          			float4 vertexColor : COLOR;
          		};
          
          		VertexOutput vert (VertexInput v) {
          			VertexOutput o;
          			o.pos = UnityObjectToClipPos(v.vertex);
          			o.uv = v.uv;
          			o.vertexColor = PMAGammaToTargetSpace(v.vertexColor);
          			return o;
          		}
          
          		float4 frag (VertexOutput i) : SV_Target {
          			float4 texColor = tex2D(_MainTex, i.uv);
          			#if defined(_STRAIGHT_ALPHA_INPUT)
          			texColor.rgb *= texColor.a;
          			#endif
          			
          			 // Calculate final alpha
          			float finalAlpha = texColor.a * i.vertexColor.a;
          			
          			// Use smooth transition instead of hard clipping
          			float lowerBound = _AlphaClip - _AlphaFeathering;
          			float upperBound = _AlphaClip + _AlphaFeathering;
          			
          			// If alpha is less than lower bound, discard pixel completely
          			if (finalAlpha < lowerBound)
          				discard;
          			
          			// Use smooth transition in boundary area
          			if (finalAlpha < upperBound) {
          				// Calculate attenuation factor - smooth transition in boundary area
          				float t = (finalAlpha - lowerBound) / (2.0 * _AlphaFeathering);
          				float alphaFactor = smoothstep(0.0, 1.0, t);
          				
          				 // Randomly discard some pixels to create feathering effect
          				if (alphaFactor < frac(sin(dot(i.uv, float2(12.9898, 78.233))) * 43758.5453))
          					discard;
          			}
          			
          			return float4(0, 0, 0, 0); // Do not output color
          		}
          		ENDCG
          	}
          
          	// Pass 2: Renders color, but doesn't write to depth
          	Pass {
          		Name "Normal"
          		ZWrite Off
          		Blend One OneMinusSrcAlpha
          		
          		CGPROGRAM
          		#pragma shader_feature _ _STRAIGHT_ALPHA_INPUT
          		#pragma vertex vert
          		#pragma fragment frag
          		#include "UnityCG.cginc"
          		#include "CGIncludes/Spine-Common.cginc"
          		sampler2D _MainTex;
          		float _AlphaClip;
          
          		struct VertexInput {
          			float4 vertex : POSITION;
          			float2 uv : TEXCOORD0;
          			float4 vertexColor : COLOR;
          		};
          
          		struct VertexOutput {
          			float4 pos : SV_POSITION;
          			float2 uv : TEXCOORD0;
          			float4 vertexColor : COLOR;
          		};
          
          		VertexOutput vert (VertexInput v) {
          			VertexOutput o;
          			o.pos = UnityObjectToClipPos(v.vertex);
          			o.uv = v.uv;
          			o.vertexColor = PMAGammaToTargetSpace(v.vertexColor);
          			return o;
          		}
          
          		float4 frag (VertexOutput i) : SV_Target {
          			float4 texColor = tex2D(_MainTex, i.uv);
          
          			#if defined(_STRAIGHT_ALPHA_INPUT)
          			texColor.rgb *= texColor.a;
          			#endif
          
          			// Keep alpha test consistent
          			float finalAlpha = texColor.a * i.vertexColor.a;
          			clip(finalAlpha - _AlphaClip);
          
          			return (texColor * i.vertexColor);
          		}
          		ENDCG
          	}
          
          	// Caster Pass (unchanged)
          	Pass {
          		Name "Caster"
          		Tags { "LightMode"="ShadowCaster" }
          		Offset 1, 1
          		ZWrite On
          		ZTest LEqual
          
          		Fog { Mode Off }
          		Cull Off
          		Lighting Off
          
          		CGPROGRAM
          		#pragma vertex vert
          		#pragma fragment frag
          		#pragma multi_compile_shadowcaster
          		#pragma fragmentoption ARB_precision_hint_fastest
          		#include "UnityCG.cginc"
          		sampler2D _MainTex;
          		fixed _Cutoff;
          
          		struct VertexOutput {
          			V2F_SHADOW_CASTER;
          			float4 uvAndAlpha : TEXCOORD1;
          		};
          
          		VertexOutput vert (appdata_base v, float4 vertexColor : COLOR) {
          			VertexOutput o;
          			o.uvAndAlpha = v.texcoord;
          			o.uvAndAlpha.a = vertexColor.a;
          			TRANSFER_SHADOW_CASTER(o)
          			return o;
          		}
          
          		float4 frag (VertexOutput i) : SV_Target {
          			fixed4 texcol = tex2D(_MainTex, i.uvAndAlpha.xy);
          			clip(texcol.a * i.uvAndAlpha.a - _Cutoff);
          			SHADOW_CASTER_FRAGMENT(i)
          		}
          		ENDCG
          	}
          }
          CustomEditor "SpineShaderWithOutlineGUI"

          }

            Harald I'm migranting my project to Godot, So, I'm waitting Godot4.4 runtime, i'll solve this problem in Godot again.

              suanLoBeach sorry to foget to post my code, I add these codes into spine/skeleton shader

              Thanks for the update. Reading your code and looking at the screenshot again now explains why the border looked as it is, I was wondering if you had some compression artifacts leading to the dot-pattern.

              I wonder why you are using dither-style feathering though, as a standard threshold might look better with typical the image outlines, which are just a gradient alpha. The purpose of dither patterns is usually where a homogenous area needs to become transparent, there you can't solve it with a single tweaked threshold. If you know what you're doing it's fine of couse, you might have your reasons.

              suanLoBeach well, I just wanna ask , Can the perfect feature be achived ? (only show the top transparent pixel)

              Perfect alpha blending showing the same result as a render texture would: no, as I said above multiple times. Otherwise we would have provided it in the example scenes instead of the render texture component.

              suanLoBeach I'm migranting my project to Godot, So, I'm waitting Godot4.4 runtime, i'll solve this problem in Godot again.

              Good luck with the migration. Note however that the problem will not change in the slightest 🙂.

                Harald

                Harald I wonder why you are using dither-style feathering though, as a standard threshold might look better with typical the image outlines, which are just a gradient alpha. The purpose of dither patterns is usually where a homogenous area needs to become transparent, there you can't solve it with a single tweaked threshold. If you know what you're doing it's fine of couse, you might have your reasons.

                Because my texture is made by the ink flow diffusion drawing method, there will be many places with high transparency. If I don't use dither, the top model will have many very transparent areas that block the objects behind. Visually, it looks like it is blocked by air. For example, the trunk of the tree in my screenshot. If I don't use dither, part of the outer side of the trunk will also block the objects behind.

                  suanLoBeach If I don't use dither, the top model will have many very transparent areas that block the objects behind.

                  Not if you set the _AlphaClip threshold properly to exclude these areas of high transparency. You receive jagged outines instead then, obviously.

                    Harald Can I do that on many texture in a same skeleton ?
                    different mesh, different texture, like those leaf, in the same skeleton

                    Harald How to do it ? the texture have the same Z value, they are on a same plane

                    Harald oh, it's what i need ,thx

                    I have another quastion, I wanna leaf is dynamic by vertex displacement,but stem is static, now they use the same material , so How can I make two different affect, I'll add teh code about vertex displacement into my custom spine shader, but there is only one material slot here, do i need to make two slot in spine and how to make it ?

                      suanLoBeach I'll add teh code about vertex displacement into my custom spine shader, but there is only one material slot here, do i need to make two slot in spine and how to make it ?

                      I'm not sure which Material slot you're talking about, but if you want different materials for different slots, see the SkeletonRendererCustomMaterials component.

                      In general please always check out the spine-unity documentation pages first and the example scenes that come with the spine-unity runtime. For common tasks there is almost always an entry in the documentation or example scene available.

                        Harald So the step of customizing the materials of multiple components is done in Unity? Is there anything I need to do in Spine?

                        Harald I have know how to set custom material for any slot, thanks

                          suanLoBeach Glad to hear you've figured it out, thanks for getting back to us.