Harald https://discussions.unity.com/t/overlapping-transparent-shaders/816073
acturlly I want this affect,but I don't know if it's URP or built-in RP
Harald https://discussions.unity.com/t/overlapping-transparent-shaders/816073
acturlly I want this affect,but I don't know if it's URP or built-in RP
Harald 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 ?
suanLoBeach You can't solve this problem with any standard rasterizer-based rendering API which renders triangle after triangle - not using Built-In RP, not URP, not HDRP.
suanLoBeach But why did someone on the Unity forums succeed?
Did you look at the linked images in the forum thread you mentioned? They have a normal 3D mesh without semi-transparent textures at the outer edges which they want to make semi-transparent. They don't have a texture with an alpha gradient that they overlap.
Normal skeleton attachment images have a semi-transparent outline with an alpha gradient. If you use any buffer like stencil or Z-buffer for discarding overlapping pixels further back, you can only choose a single threshold value where a semi-transparent texel will be considered as writing to the buffer, or not writing to the buffer. This results in a hard cutout effect around the outer edges.
There is a reason that Unity provides render queues Alpha Test
separate from Transparent
. Alpha Test
has a cutout effect using an alpha threshold and writing to the z-buffer. Transparent
renders back to front (like the Spine skeletons, as they are transparent) and let everything overlap transparently with whatever was behind it.
suanLoBeach https://discussions.unity.com/t/overlapping-transparent-shaders/816073
acturlly I want this affect,but I don't know if it's URP or built-in RP
The render pipeline does not matter.
Again, this is simple mesh based binary masking, all-or-nothing, as described above.
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 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
@suanLoBeach Yes.
Harald How to do it ? the texture have the same Z value, they are on a same plane
@suanLoBeach Set Advanced
- Z-Spacing
at the SkeletonAnimation
component.
https://esotericsoftware.com/spine-unity-main-components#Setting-Advanced-Parameters
You likely want to set this parameter to a value other than 0.0 whenever writing to the Z buffer.
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?