- Home /
Why does it say set ZWrite to off when semi-transparent shading in the docos
In the shader documentation it says:
ZWrite On | Off Controls whether pixels from this object are written to the depth buffer (default is On). If you're drawng solid objects, leave this on. If you're drawing semitransparent effects, switch to ZWrite Off. For more details read below.
It doesn't ever elaborate any further though. So I thought this meant that for some reason that having it on would have no effect if your objects were transparent.
But today - to try and solve a longstanding problem with multiple close transparent objects jumping over the top of one another at certain camera angles - I was fiddling around and turned it on and lo and behold my problem went away.
Now, I am not in fact surprised by the result but I am a little confused by the documentation. What is it saying?
Answer by Noise crime · Aug 09, 2010 at 03:09 AM
With zWrite on polygon depths are written to the zbuffer effectively giving you perfecting sorting (avoiding the painters algorithm issues - look it up). So if you had a polygon at z=100 any future polygons that are further than z=100 will not be rendered.
However this does not mean it prevents overdraw as it depends upon the order of models/meshes/polygons being rendered. I.e if you render a polygon at z =100 then one at z=80 you'll still have rendered the further one, even though the closer one obscures.
So when applied to transparent models, its down to pure luck or careful orchestration of the render order to ensure that object maintains its transparency with other models or its own polygons. For example if you have two transparent polygons, the first is rendered at z =80, then the second at z=100 will not be rendered as its further than the depth in the zbuffer, meaning it will not be visible.
When turning zWrite Off, the polygons do not write their depth to the zbuffer, meaning without sorting transparent object and their polygons you will likely get incorrect draw orders, which is what you saw (again this is due to the issue from the 'painters algorithm').
However its impractical to sort per polygon, even more so if two models with different materials overlap, performance will simply nose-dive.
Often the way around this, at least for vegetation, foliage, trees & bushes is to fall back on the alpha test. Here are a boolean alpha test is carried out to see if the pixel should be drawn (and I guess write to the zbuffer, thus giving correct draw order for transparent materials). The drawback is being a boolean operation is that you get aliasing/jagged borders. To reduce this effect the vegetation is normally rendered again, but this time blended with zwrite off. It suffers the draworder problems as before, but as only the edges will render it helps to give a smoother transition than the boolean.
Oh and I should point out that the counterpart zRead is required for correct rendering not just zwrite.
Once you understand zWrite and zRead you can do some funky stuff with it, especially in conjunction with colorMask.
So with the case where I have zwrite On, I might see the BEHIND transparent object missing, but I won't see the BEHIND object rendered over top of the INFRONT transparent OBJECT. Is that correct?
For me that is a lesser evil than the alternative you posted above as unusual artifacts will be more obvious in what I am doing.
yes thats right as long as zTest is active (thx Jessy, knew zRead didn't sound right but it was like 4am when i replied ;) )
Answer by Jessy · Aug 09, 2010 at 03:00 AM
All the pixels from your mesh get rendered to the depth buffer. With ZWrite On, even though pixels of your mesh may be alpha blended so that they don't contribute any color, they still get written to the depth buffer. If other meshes are sent to be drawn by the GPU later, then they might not have all of their pixels rendered. This is because by default, rendering only occurs if a pixel is closer to the camera than what has already been put into the depth buffer. Generally, sorting objects from far to near helps, and Unity does this at least in some rendering queues (though documentation on this is nil so I don't know the specifics). However, the sorting is based on the center of the axis-aligned bounding box, so it doesn't work well for objects that are very big, or that are rather parallel to the camera's Z-axis. (I go into some detail about all this in chapter 6.)
ZWrite Off is not a cure-all, however, as I talk about in video 7-1. (If it were a cure-all, then the depth buffer never would have been invented. :-P) If you're using other forms of blending (like additive), ZWrite Off can be perfect, but it can't be for alpha blending, where order of rendering matters. The alpha testing page in the ShaderLab manual offers a compromise between alpha blending and alpha testing, that can work well if your mesh is mostly opaque.
Your answer
Follow this Question
Related Questions
Z-priming alpha-per-vertex 0 Answers
shader causes triangles to dissapear in U4 (worked in U3) 0 Answers
Shader for overlaying textures 1 Answer
Minimap camera transparency 1 Answer
Transparency shader that also writes to Camera Depth Texture 0 Answers