How can I stop my transparent shader from creating voids?

I am working on a skin shader which needs to be able to handle transparency but at the same time not have the usual depth buffer issues that the builtin transparent shaders have. I have added an extra pass to solve this. At the moment I am using a Queue tag of “Transparent-1”, which handles very well in relation to other transparent objects that are behind and infront. However the problem comes when I try to make the material completely transparent, since it creates a hole or void in its place:

alt text

I’ve found I can solve this by simply changing the Queue tag to “Transparent”. This gets rid of the void when completely transparent, but instead creates some z-fighting issues with other transparent objects. Notice the 6 figures in the red cube volume (please excuse their strange test outfits):

alt text

If we look at the red volume from an ortho top view you’ll notice that all the 6 figures are clearly inside it, yet in the above screenshot the z-fighting is making them appear as outside of it.

alt text

Any suggestions on how I should fix this, is there a particular property that would be helpful in my case? I’ve been playing around with this shader for quite some time now and I can’t come up with anything.

Here is my shader code:

Shader "Player/Human Skin" {
Properties {
    _Color ("Main Color", Color) = (1,1,1,1)
    _SpecColor ("Specular Color", Color) = (0.5, 0.5, 0.5, 0)
	_Shininess ("Shininess", Range (0.01, 1)) = 0.078125
    _MainTex ("Base (RGB) Trans (A)", 2D) = "white" {}
    _AlphaMap ("Transparency", 2D) = "white" {}
    _BumpMap ("First Normal Map", 2D) = "bump" {}
 
    // Slider to control fading between normalmaps
    _BumpMapSlider ("Normal Slider", Range (0, 1)) = 0
 
    // Second normal map
    _BumpMap2 ("Second Normal Map", 2D) = "bump" {}
}
 
SubShader {
    Tags { "Queue"="Transparent" "IgnoreProjector"="False" "RenderType"="Transparent" }
    LOD 400
 
//For getting rid of Z-fighting
Pass {
        //ZWrite On
        ColorMask A
    }

CGPROGRAM
#pragma surface surf BlinnPhong alpha
#pragma exclude_renderers flash
 
sampler2D _MainTex;
sampler2D _AlphaMap;
sampler2D _BumpMap;
fixed4 _Color;
half _Shininess;
 
// Remember to add your properties in here also. Check ShaderLab References from manual for more info
float _BumpMapSlider;
sampler2D _BumpMap2;
 
struct Input {
    float2 uv_MainTex;
    float2 uv_BumpMap;
};

void surf (Input IN, inout SurfaceOutput o) {
    half4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    o.Albedo = c.rgb;
    o.Gloss = c.a;
    o.Alpha = c.a * tex2D(_AlphaMap, IN.uv_MainTex).r;
    o.Specular = _Shininess;
    
    // Read values from _BumpMap and _BumpMap2
    fixed3 normal1 = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    fixed3 normal2 = UnpackNormal(tex2D(_BumpMap2, IN.uv_BumpMap));
 
    // Interpolater between them and set the result to the o.Normal
    o.Normal = lerp(normal1, normal2, _BumpMapSlider);
}

ENDCG  
}
 
FallBack "Transparent/Bumped Diffuse"
FallBack "Transparent/VertexLit"
}

The reason I use the extra pass. Without it the inner parts (mouth, teeth etc) of my character are visible through their head. Notice the big black poke through:

alt text

If there is nothing to render, turn off the renderer.

If that doesn’t work for you, for some reason I can’t predict, then you need to render the beefcakes in the box in an earlier queue than the box, because the center of the box is farther away than a couple of the beefcakes. Farther objects get rendered first.

If you don’t want to see them, I suggest you “dont draw them” :slight_smile:

So I can think of a couple of ways of doing that. First of all - don’t have them (I use different legs/arms/torso when using different clothing to save all of those vertices and polygons which will never be seen).

Secondly you could mark the vertices in those triangles in some way - UV2, Vertex color or something, so each hideable body part is marked differently. Then in your vertex program rather than actually mapping the position of a vertex for a section that should be invisible at present just tell the GPU that its at -1000,-1000,-1000 in eye space so that it just never gets drawn. That’s much faster because there won’t be any fragments to shade for those parts of the model. This does of course require you to suppress at the triangle level so there would have to be sensible vertices to hide in the legs if you are drawing pants etc.

Third way is when the clothing changes calculate which triangles can be seen in a T pose, by using a shader that renders the triangle number to a few render textures by moving a camera around the model, or by doing the math on the visibility of each triangle and then bake a model that only contains the visible triangles which becomes the one you actually draw. You could actually bake these in the editor and then you’d know which you can actually include (it’s pretty much a suggestion of automating the process in 2 and then baking a static mesh to make the shader faster). EDIT: You actually probably need to write the vertex number on reflection, rather than the triangle number and then work out which triangles that vertex is a part of.

But perhaps a cutout shader is the right way for you? You appear to mostly want something to be totally not there and others to fade into the background right? A depth writing transparent shader will let you fade in properly to whatever’s behind your model and a cutout shader will dispense with the parts that are supposed to be totally missing. Cutout shaders suck on mobile platforms because they break some of the optimisations, but that might be your best bet if you don’t want to follow the vertex route.