• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Prefab · May 17, 2013 at 04:52 PM · shadertransparentz-fighting

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

Comment
Add comment · Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Jessy · May 17, 2013 at 07:30 PM 1
Share

That is not what Z-fighting is.

avatar image whydoidoit · May 17, 2013 at 07:39 PM 2
Share

So the effect you are getting is due to the relative sort of the objects being drawn. The problem being that transparent shaders can't write to the Z buffer and so the order is based on how far away from the camera they are (as a whole), that means your zone is further away (draw before) the two closer characters, but closer than the others.

It's a hard problem to fix, because the moment you write to the Z buffer, you will make a hole.

A Cutout shader would drop transparent pixels (and not write to the Z buffer) but then you may have ragged edges due to the "I'm writing or I'm not" nature.

Can you explain what the purpose of your transparent skin is?

avatar image whydoidoit · May 17, 2013 at 07:41 PM 0
Share

To clarify (it's possible to do clever tricks with self transparency in multiple passes, it's much harder to do that and not end up playing dirty with big transparent areas elsewhere).

avatar image Prefab · May 17, 2013 at 08:25 PM 0
Share

Ok, this is probably going to be a long explanation but I'll try to make it clear.

The first and main reason I need the skin to be transparent is for "poke through". The body mesh in the pics above has the clothing meshes hidden but in actual fact there is: the body, pants on top of that, a jacket on top of both of those, shoes etc. Even though both the body and all the clothing models have very similar skinning, some poke through still occurs during animation which is why I would like to have a transparent skin shader. I can mask out the parts of the body covered by clothing eg. mask out legs underneath the pants, this is why the shader has a separate alpha map.

The second reason is similar to the first, I need to be able to mask out body parts under the clothing when I am making the clothing "invisible" (blend into its surroundings via transparency) at runtime. Note I can't turn the renderer off here for the entire body because no clothing model covers the entire body mesh, so I need the body part masking to be flexible enough to only cover certain parts of the body.

This is why I'm using this shader. The extra pass is to prevent the mesh from looking like this: http://docs.unity3d.com/Documentation/Components/SL-CullAndDepth.html But because it is an extra pass it makes one extra drawcall. I wish I could eli$$anonymous$$ate this extra drawcall but I'm not sure how to while doing what I need this shader to do.

2 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by whydoidoit · May 17, 2013 at 08:58 PM

If you don't want to see them, I suggest you "dont draw them" :)

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.

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Prefab · May 18, 2013 at 06:08 AM 0
Share

I think the cutout shader is the best and simplest idea, because the other suggestions are unfortunately beyond my scripting depth :). The problem is that there will be times when I need to see the body mesh (legs, arms, etc) and times when I don't (when clothing is covering it).

I'd tried using a cutout shader before because it gave me both transparency and opaque geometry without the sorting problems. The issue I ran into was making the alpha cutout slider work with the separate alpha texture and double normal maps; and when I changed the surface surf to #pragma surface surf BlinnPhong alphatest:_Cutoff, which is what cutout shaders use, I got an error also. If you look at my shader you'll notice that the alpha is controlled by both the _Color and a separate _Alpha$$anonymous$$ap texture 2d input. Both can bring the material to 100% transparency but they can do this individually as well, whereas a cutout normally uses only one alpha texture/map I think.

I'll try this again and post back if I have more issues. Hopefully it works ;)

avatar image Prefab · May 18, 2013 at 06:46 AM 0
Share

Ok it's working perfectly now, I just have one more question. I ran into an error on the way: Program 'frag_surf', Arithmetic instruction limit of 64 exceeded;

Which apparently means that I am exceeding the capabilities of shader 2. So I added: #pragma target 3.0, to get rid of it. Are there any limitations of targeting shader 3 ins$$anonymous$$d of 2, most graphics cards nowadays can handle shader 3 can't they?

avatar image whydoidoit · May 18, 2013 at 06:59 AM 0
Share

Yes they can if you are targeting computers. $$anonymous$$obile devices really need to not use surface shaders anyway (they do too much clever stuff!) and you'd probably be able to build it to S$$anonymous$$2 by writing a vertex/fragment shader rather than a surface shader (you might not use as many lights for instance).

avatar image Prefab · May 18, 2013 at 07:26 AM 0
Share

I actually only use one light in my entire scene (for the sun, that's all) so that should be fine. Where can I find out more about the vertex/fragment shader stuff? I'm not ai$$anonymous$$g for mobile devices but I'd still like to try to convert my shader for performance reasons. Are the builtin mobile shaders a good start?

avatar image whydoidoit · May 18, 2013 at 07:36 AM 1
Share

Right well surface shaders produce (complicated) vertex/fragment shaders when they are compiled. So you can actually view your compiled shader in Unity and see all of the different ones that were created. V/f shaders are the more common approach so there's a fair bit of doc online.

I wrote a tutorial on Unity Gems that covers my journey of learning shaders. It starts with Surface shaders and moves on to Vertex/Fragment shaders in the process. There are also some really good links in the first section to other peoples stuff.

The hardest thing about Vertex/Fragment shaders is writing the lighting calculations and finding documentation for all of the Unity elements (like shadows etc) but it's all doable. You can also open the UnityCG.cginc file that's part of the Unity installation and look at how they do things like shade vertex lights etc. Surface shaders do magic with your inputs etc, V/F shaders do that stuff by hand (and for me that's actually more useful).

Show more comments
avatar image
1

Answer by Jessy · May 17, 2013 at 07:35 PM

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.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Prefab · May 17, 2013 at 08:32 PM 0
Share

(Also, please read the explanation I gave in the comment above)

Think of it this way; the body meshes are going to be the players (3rd person) and NPCs, the transparent box was supposed to represent a house/interior with windows. Obviously when a player/npc goes inside a house you don't want them to look like they're still outside because all the windows get rendered in the wrong order.

I have a simplified (Transparent Diffuse) version of the above shader which I could place on all the windows so that the player/npc and windows would get drawn in the correct order in relation to each other. But this would be expensive because the extra pass in the shader generates an extra draw call which would add up quite fast considering the number of players, npcs and windows in each scene. $$anonymous$$aybe if I could find a way to drop that draw call while still achieving what I need with this shader, I could then apply it to all the windows and the problem would be solved. What do you think?

The only reason I use that extra pass is because I can't have my players/npcs looking like this: http://docs.unity3d.com/Documentation/Components/SL-CullAndDepth.html at 0% transparency. If there is a better way I'm all ears.

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

15 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Transparent Shader Render Order Issue 0 Answers

Can i force a renderer with standard shader material to crossfade? 0 Answers

Transparent w/ Full Shadowcasting in Unity 5 1 Answer

Transparent Objects within Transparent Objects 1 Answer

Why my 2d character would not be displayed correctly at the very beginning? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges