Fancy Ghosts!! How can I invert the zwrite functionality?

Dear shader gods,

I have an interesting problem, which has been puzzling me for some time. I’ll summarize first, and then go into a little more detail:

I have a number of ghosts, which I would like to appear in a scene. I want them to be semi-transparent so I can still see “solid” objects behind them, but I also want the ghosts to block other ghosts.

I have forced this effect in the image below using queues. The semi-transparent objects are rendering closest to farthest away:

1611319--97877--$Untitled.png

If I use a standard transparent shader, I get the following blending, which I don’t want:

1611319--97878--$Untitled2.png

How can I create this effect without depending on queues? I ultimately want a single shader, and an unknown number of ghosts. I will not know where the ghosts will be in the scene, nor will I know where the camera will be. Is there a way to invert the depth information from zwrite so the ghosts will always be rendered from closest to farthest away based on distance from the camera? Am I even on the right track?

Thanks

You can write a Z-priming shader that runs after opaque, but before transparent geometry. It should use AlphaMask 0 to write only to the depth buffer.

Make a Material using this shader, and add it to all the transparent renderers you would like to occlude one another. Note that you should add the new Material to each renderer rather than replacing the existing material.

Thanks!!!

I actually ended up using a two pass shader so I wouldn’t have to add a second material. Here it is for everyone else:

Shader "Transparent/VertexLit with ZPriming" {
Properties {
    _Color ("Main Color", Color) = (1,1,1,1)
    _SpecColor ("Spec Color", Color) = (1,1,1,0)
    _Emission ("Emissive Color", Color) = (0,0,0,0)
    _Shininess ("Shininess", Range (0.1, 1)) = 0.7
    _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
}
 
SubShader {
    
    Pass {
        Tags {"Queue"="opaque+1"}
        ColorMask 0
    }
    
    Pass {
    	Tags {"RenderType"="Transparent" "Queue"="Transparent"}
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha
        ColorMask RGB
        Material {
            Diffuse [_Color]
            Ambient [_Color]
            Shininess [_Shininess]
            Specular [_SpecColor]
            Emission [_Emission]
        }
        Lighting On
        SetTexture [_MainTex] {
            Combine texture * primary DOUBLE, texture * primary
        }
    }
}
}

I could be wrong, but it might only be luck that your current solution works. My reasoning is that “Queue” is a Subshader tag rather than a Pass tag. I’m not sure it’s actually doing anything in your shader as written. Instead, the passes get executed in the order they appear (which is fine), but the Subshader is being run in the default (Geometry) queue.

If I’m right, you’re liable to see strange interactions between your transparent things and actual opaque objects, as well as other undesired behaviour.

However, if Queue tags are also secretly Pass tags, then what you’ve written should be fine in every case, and Unity should fix their documentation to reflect this.

Edited to add: It looks like Jessy agrees with my understanding of the behaviour, and I would tend to trust his knowledge of Shaderlab before nearly anyone else’s.

You’re completely right. I did luck out.

Thanks for the follow up. I respect Jessy’s input, and really appreciate your further explanation of the tags. I think I have a good understanding of the situation now.