1
\$\begingroup\$

I am building a 2D game using sprites. I'd like to use the z-buffer to aid with shading.

For that I need Unity to write only opaque pixels to the z-buffer (aka depth buffer). In Unity, sprites are built up of polygons, and it is writing these entire polygons, including the transparent pixels, to the depth buffer.

This is the shader I'm using (with some junk added while trying to get this to work) http://pastebin.com/khprCUA0

I have tried

  • AlphaTest Greater 0
  • alphatest:MyAlphaTestVar
  • the discard keyword
  • Cg's clip function
  • I suspected that a lighting pass might be writing the depths so I added novertexlights and noambient

I would suspect that AlphaTest prevents transparent pixels from having any effect on the frame or depth buffer (as suggested here), but they still do write to the depth buffer!

The screenshot below shows the inaccurate shapes of objects in the Z-buffer. The king and tree have become blobs because even their transparent pixels were updated in the Z-buffer (drawn using http://willychyr.com/2013/11/unity-shaders-depth-and-normal-textures/): enter image description here

Compare this to the "correct" shape of the objects in the regular view: enter image description here

How do I get Unity to not write transparent pixels to the z-buffer?

EDIT:

Unity 5's frame debugger is turning out to be a miracle! Turns out the "Depth Texture" is actually rendered in a separate pass before all other geometry. And I'm having trouble finding out how to use RenderType to include/exclude certain objects from this pass.

\$\endgroup\$
  • \$\begingroup\$ See stackoverflow.com/questions/19819376/… But my guess is that you have another pass screwing things up, as alpha testing should do what you want. \$\endgroup\$ – Khlorghaal Jan 24 '15 at 7:02
  • \$\begingroup\$ I am starting to think it is indeed another pass that is writing the zbuffer. But I created a scene without lights, and the transparent pixels are still written. What other passes is Unity doing and how can I influence them? \$\endgroup\$ – noio Jan 26 '15 at 10:18
1
\$\begingroup\$

Found! (Thank you Frame Debugger !)

It turns out that Unity renders the Depth Texture in a separate pass before all geometry is rendered. It is hard to find how to include objects in this pass, and how to specify how they are drawn.

enter image description here

The documentation is kind of vague, but it tells you that the "RenderType" is important without specifying what it should be in order for objects to be included in this pass. I found out that a SubShader will render if it specifies

"LightMode" = "ShadowCaster"

So, my shader needed a separate SubShader that also performs an AlphaTest with this LightMode set. This in addition to the 'regular' SubShader which will draw the sprites; which might not even need an AlphaTest since the zBuffer is not used for the DepthTexture on my setup. The documentation suggests that some hardware/OS/rendering setups will use the zBuffer but it's not entirely clear.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.