I’m getting incorrect rendering on objects that both are using the Unity transparent/diffuse shaders. If I move the camera back slightly the foliage gets obscured behind the tree trunk.
I’ve tried researching this but I can’t find what seems to be the accepted solution. Some unity forum posts say to change the transparent ordering in the shaders, some say to turn on Z-Write buffering for all shaders, some suggest changing the camera settings, some say it’s a bug to do with occlusion culling. What is the actual problem and what is the correct solution in this circumstance?
The problem is due to how transparent objects are sorted in Unity. Usually, objects are drawn using the z-buffer, which draws a depth image as it renders the scene. This ensures that only the closest pixel is drawn, so everything appears in the right order. The problem occurs with transparent objects, or, more precisely, semi-transparent pixels. When objects are semi-transparent, they cannot be accurately written into the depth buffer. This is because the z-buffer makes the assumption that only one object will need to be drawn in any one pixel on the screen, in exchange for extremely fast sorting. Semi-transparent objects require multiple pixels to be drawn at the same point, and so they have to be drawn either before or after the rest of the image. Naturally, this produces some sorting errors, because per-pixel sorting, as found in the depth buffer, is not feasible. In Unity, the sorting method just takes the centre point of the mesh, and assumes that the entire mesh lies at the same depth value. The practical upshot of this is that if the centre of your transparent object goes behind another object, then the entire object will be rendered behind it.
Now that we’ve discussed the cause, let’s talk about solutions. There are, in fact, a few possible ones, though they all involve trade-offs. I’ll discuss 3 here:
- Cutout Shaders. Cutout shaders solve this problem by applying a filter to the texture, giving every pixel a boolean value: visible or not visible. This allows complex shapes to be drawn, and since no pixel is semi-transparent, the depth buffer to be used. The trade-off here is with smoothness - you will lose the nice, soft edges you get with transparent objects. This is the most accurate solution, and for small, distant, or high-res textures, this is definitely the best one.
- Segmented Meshes. This is a little more difficult to get right, and is only an approximation. The idea is that instead of having one large mesh, you separate it into several small ones, each carrying a part of the texture. Since the transparency sorting is on a per-mesh basis, this will allow the problem to become rarer, as each part of the object can be sorted individually. The trade-offs here are in performance, and difficulty of implementation.
- Z-Writing. Another option is simply to write to the z-buffer anyway. This does work, but does produce some artefacts. Any other semi-transparent object drawn will either always be above, or always be behind, the object you’re drawing, meaning depth sorting between this object and other transparent ones will simply disappear. This is often a good solution if you will very rarely overlap objects, or if your object is against a surface such that no other transparent object will pass beneath it.
There are more possible solutions, but these are some of the more common ones. The reason you have so much trouble finding one solution is that there isn’t one - there are several. Each has their benefits and their drawbacks, and it’s up to you to decide which suits your needs best.
simply change the render queue:
- select Object Material
- change view to Debug Mode (Inspector Window top right drop down menu)
- change Custom Render Queue value for example 3000 => 3100
- now your object will be rendered before other transparent objects
Thnxx so much for the help!!!
In my case I had an open, top-down look into an apartment-like area. Since I wanted “sunlight” to come in through the windows I created a transparent plane to “block” the sunlight and prevent it from seeping in through the open roof, allowing it to shine through the windows…and THAT is why the Occlusion effect was NIOT rendering…as soon as I eliminated the transparent plane everything came back to normal…so THNXX!!!