I am trying to render a 2D character that has 6 different parts(head/body/arms/legs/sword/shield). All parts are separate sprites but they all have the same dimensions and pivot point.
I also have a depth texture for each sprite, in same dimensions as main sprites. I will convert them to alpha value of the main sprites for performance reasons later.(Please look at the first comment for depth textures, I cant add more files)
For all parts of the character I want only the fragment with the highest alpha value(per pixel) to render, but I don’t know how to achieve that. Any help is appreciated.
Some notes:
The character will have flipbook animation, so the main textures will keep changing
Sprite sorting wont cut it because one limb can be above and below another limb at the same time.
There will be other characters in the scene with a similar setup, so I need the fragment sorting done per character if that makes sense
I am a complete beginner with hlsl
Something like this could possibly work, but I don’t know how it would work with flipbook sprites. Just using rgb values from the highest alpha value per character part is the easy part
To do per-pixel depth sorting you need to render your sprites using a shader that is opaque and uses alpha testing instead of alpha blending. Then you would need to have your sprites output their per pixel depth from the fragment shader. If you want multiple characters to sort separately and not intersect you either need to actually keep them separated in Z space.
Alternatively you would need to render each character into a render texture separately and then use the resulting render texture when rendering them into the scene.
The post you linked to which blends multiple textures together is only possible when all of the textures are being rendered by a single mesh. The fact your body parts are separate sprites excludes this as an option. Unless you use something like the aforementioned render texture approach and render each individual sprite to a render texture and then combine those.
interestingly enough order in layer doesn’t work for the custom shader but I don’t mind it, I have decided to use it on just the player anyway.
Toggling ZWrite doesn’t seem to change anything but it still works.
here is the full shader code if anyone is interested. Let me know if you have any comments/tips about the shader code.(PS: I’ll combine the main & depth textures to reduce sampling and size later)
Shader "Custom/2D"
{
Properties
{
[PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
[PerRendererData] _DepthTex ("Depth Texture", 2D) = "white" {}
}
SubShader
{
Tags
{
"Queue"="Geometry" //setting to Transparent doesn't seem to change anything
"RenderType"="Opaque" //setting to Transparent doesn't seem to change anything
}
ZWrite On//enabling or disabling doesn't seem to change anything
//ZTest LEqual
Blend SrcAlpha OneMinusSrcAlpha//necessary for removing 'artifacts' also need to set alpha is transparency to false in depth texture
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _DepthTex;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
struct fragmentOutput
{
fixed4 color:SV_Target;
float depth:SV_Depth;
};
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos (v.vertex);
o.uv = v.uv;
return o;
}
fragmentOutput frag(v2f i)
{
fragmentOutput output;
output.color= tex2D(_DepthTex, i.uv);
output.depth=tex2D(_DepthTex, i.uv);
return output;
}
ENDCG
}
}
}