I have a series of sprites all on the same z-axis. I’d like to be able to merge their central color and not have their outline overlap, and be able to set its central color and outline. Just like the example below:
I’ve figured out how to assign the colors, but am unsure how to merge the sprites images. I think I could set the z-depth or use a grabpass, but those are expensive on mobile devices, right?
It looks like you’re trying to make a metaball shader. I’m not familiar with how it’d be implemented in ShaderLab though. I know that a long-time ago there used to be a screen-space ShaderLab tutorial for it though.
That is definitely one solution, Daniel. Have a separate outline sprite sitting below the base sprite. That’s a lot of overdraw though, and this feels like it can be done with a shader. And it’s a good exercise for me to learn more about shaders.
Yes that’s exactly what I’m thinking of! But I’ve pored over tons of shaders and forum posts and still cannot figure out how to manipulate the zdepth. Can you point me in the right direction?
I don’t think you can change depth values from a fragment shader on mobile. The deferred renderers used by all the hardware would have a really hard time with that even if they could do it, and doubling your overdraw would definitely be a faster solution.
Can anyone provide me a simple example of using a texture to set the z offset? It may very well be the wrong direction, but it’s something I’m interested in seeing and testing.
And thoughts on using a grab pass and manually blending each pixel?
Ok then that will likely be my final solution. Thanks all for the discussion! But I’d love to see an example of using a texture to set a z-offset. I’ve been trying to figure that out for days and hate to leave a problem unfinished…
even resovle the z_fight, From your picture,i have another question:How about the outline merge? you make it use postrender?2D Sprit is different with 3d model.And if you use mesh to make the circle,then use PostRender make the outline,I think you get it easier.
Ah ha! I did not understand that you could not manipulate z-depth on a pixel-by-pixel basis. It’s done for all the geometry in the pass. I’ve made a shader that does what I want. I still may use two sprites, but still wanted to try this and share. Thanks everyone for the hints!
If anyone is interested:
Shader "Assign Colors Z"
{
Properties
{
_ColorMain ("Main Color", Color) = (0.5, 0.5, 0.5, 1.0)
_ColorBorder ("Border", Color) = (1.0, 1.0, 1.0, 1.0)
_MainTex ("Texture to blend", 2D) = "" {}
}
SubShader
{
Tags
{
"Queue" = "Transparent"
}
// Pass 1 draws all the circles with alpha. They will overlap.
Pass
{
Zwrite Off
Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
half4 _ColorMain;
half4 _ColorBorder;
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul( UNITY_MATRIX_MVP, v.vertex );
o.uv = v.texcoord.xy;
return o;
}
// Convert black to the main color, and white to the border color.
half4 frag (v2f i) : COLOR
{
// get the texture's color for this pixel
half4 color = tex2D( _MainTex, i.uv );
// get how far apart the border and main color are
half4 delta = _ColorBorder - _ColorMain;
// the final color is the percentage difference between the two. more white = more border color. less white = less border color.
half4 main = _ColorMain + (color * delta);
// manually set the alpha
main.a = color.a;
return main;
}
ENDCG
}
// Pass 2 redraws just the inner circle and pulls it towards the camera. White texture pixels become alpha.
Pass
{
Offset -1, -1
Blend SrcAlpha OneMinusSrcAlpha
// ditch any pixels with >50% alpha
AlphaTest Greater 0.5
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
uniform sampler2D _MainTex;
half4 _ColorMain;
half4 _ColorBorder;
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul( UNITY_MATRIX_MVP, v.vertex );
o.uv = v.texcoord.xy;
return o;
}
half4 frag (v2f i) : COLOR
{
// get the texture's color for this pixel
half4 color = tex2D( _MainTex, i.uv );
// set the main color for everything drawn
half4 main = _ColorMain;
// make white become transparent
main.a = min(color.a, 1-color.r);
return main;
}
ENDCG
}
}
}