When render mode on the standard shader is set to transparent I get strange z sorting errors on my model. Here is a 2 min video with narration walking through the issue. I would be grateful for any help you can provide.
This is working as expected.
Efficient, and correct sorting of 3d transparency in real time rendering is still an unsolved problem. There have been a number of attempts to fix this or mitigate it, but they all come with a fairly significant performance hit.
The way any single model is rendered is each polygon of a model is rendered in the order they exist in the model’s definition. In the case of opaque or cutout each polygon writes to the depth buffer. Each new polygon drawn will test against the depth buffer and skip those pixels that are occluded.
With transparent stuff (both fade and transparent) the polygons test against the depth buffer but do not write to the depth buffer as doing so may prevent other transparent objects from rendering behind it, but it also means sorting in model can be wrong. Just enabling depth write won’t entirely fix it either. Anything that gets rendered out of order with opaque stuff just gets overwritten by the polygons that draw later, but with transparent stuff it’s blended over what’s already rendered.
Besides, what you want isn’t actually correctly sorted transparency. You want it to look like it does when opaque, but transparent. With correctly sorted transparency when it starts to fade you’d still see “inside” the model as it fades out.
There are three ways around this.
One is a depth write pre-pass which renders all of the model’s geometry to the depth buffer once before rendering the transparency. There are basic examples of in Unity’s documentation here. I haven’t seen someone post a version of the standard shader with this technique, though one might exist on the asset store someplace.
Note: Having transparent objects write to the depth buffer can have other consequences, like other transparent objects not rendering behind it!
Another option is to render your character opaque to an offscreen buffer and composite it back into the scene as a sprite. This is complicated and kind of slow, but does give a lot more control.
Another is to pre-sort the polygons in your model. This one is harder as most 3d modelling programs don’t easily expose a way to reorder the polygons, and there’s no guarantee on export or import the order will stay constant. If your model needs to animate you’re also guaranteed that the order won’t be correct for anything but a single pose. It’s still not perfect either in the best case as any polygons that intersect will still be wrong and you can only pre-sort for one direction. So really the only option is the above depth write pre-pass.
As for why the “Transparent” setting for the standard shader still renders something, this is also working as expected. This is the specular. Something like clear optical glass is almost perfectly transparent, but will still have specular highlights. With Unity’s standard shader even with a smoothness of zero there’s still a little bit of very diffuse specular gloss which is what you’re seeing. This is why the “Fade” setting exists.
Awesome explanation @bgolus .
Just wondering out loud here - another solution might be to separate the pieces that need to be transparent in the modeling package. Rig/skin them to the same skeleton as before and they will also use the same texture as before.
When importing they will be seprate mesh objects but controlled under the same skeleton, and they will have a different shader than the rest of the opaque mesh parts, Then will the render order be correct?
And (guess) couldn’t the specular ghost anomaly be eliminated with a proper solid black specular map (metalic alpha). A 1 pixel black png with a black alpha.
Just a thought for a couple workable solutions. I might test this if OP doesn’t before I get off work.
And one draw back off the top of my head would be additional draw calls from multiple mesh objects - maybe.
Your awesome bgolus. Thanks for the in depth explanation. I don’t have any shader writing experience a the moment so would the following be a viable alternative. I could simple model out the straw hands and continue to use an opaque render mode or use a separate shader for the straw hands. I know a separate shader for the hands would be best avoided if possible, especially for mobile because of the extra draw calls. Modeling the straw adds polygons though not to many. Is this alternative still better for performance on mobile than using the cutout render mode? I guess I’m saying, for mobile, is it better to have more polygons and no transparency or less polygons and use the cutout render mode? Thanks again for your awesome reply.
If all you want is the hands to have some fade to them, then yes, separate them out to a second material (not a separate model, just apply a different material in your 3d program and Unity will understand this). It will increase the draw count, but that’s the best option for having them softly fade.
A black specular using the “Standard (specular)” shader might eliminate the specular, but you’re better off just using the fade mode.
Cutout vs transparency on mobile is a more complex question than it seems. On most mobile devices cutout is slower than transparency, though I don’t know if this is still the case with recent iOS devices. The extra draw call is going to be better than rendering the entire object as cutout though on nearly every device.
Cutout vs geometry on mobile is also a bit of a toss up. On complex enough geometry the cutout is better, but for these hands having them modelled out is likely going to be faster on most devices assuming you only want to render one or two of these at a time, otherwise cutout / transparency might be faster.
Cool, Thanks for the explanation @bgolus and thanks for the input @theANMATOR2b . About spec for the standard shader. Ya, if your using the secular model not the metallic, just us the color picker and fill the spectacular color with black. That will get rid of the outline on the straw hands I mentioned previously.
Hi - just looking for solutions to this for LWRP - are you saying that a Hair shader for example, that is 2 sided and uses an Alpha Mask (without Alpha Clipping) is not a trivial issue in Unity.
begolus: Thank you for the tip about transparency! Solved a big problem for me in one go.
Pre-made solution for standard render pipeline. Does anybody have anything for LWRP or HDRP?
http://wiki.unity3d.com/index.php/AlphaVertexLitZ?_ga=2.240169729.303854272.1573781327-1576606752.1529746758
It’s a built in feature of the built in Lit shader for the HDRP.
It’s currently not an option for LWRP or URP, and is not possible with Shader Graph for any of the SRPs, even the HDRP.
any updates for URP i tried using the render passes to write the transparent depth but it still have issues even tho it fixes it partly
Regarding HDRP’s transparent depth prepass.
Is anything else needed for correct z-ordering of transparent objects?
I’m still getting incorrect z-orders at some orientations.
FrameDebug shows the incorrect ordering within ForwardTransparent/RenderLoop.Draw.
No obvious transparent depth step, just usual DepthPyramid
Unity 2020.1 HDRPv8 and default HDRP/lit shader.
Same with SRP Batcher enabled/disabled.
Here’s the correct order…
Here’s the incorrect order
Here’s the HDRP settings