I have several layered backgrounds in my game, placed at different depths from the camera depicting hills and such, which are quads with textures that are transparent at the top part depending on the alpha. The transparency is achieved through blending using the following keywords.
Blend SrcAlpha OneMinusSrcAlpha
Tags {“Queue” = “Transparent” “RenderType” = “Transparent” }
Now I want to use a post processing effect which utilizes the z-buffer to determine the color depending on the depth (so that it becomes darker at further distances). However, the quads with transparent pixels (or is it vertices? when is the z-buffer actually written to?) do not seem to write to the Z-buffer so they are not affected by my post processing script.
I have tried using the “cut out” method using the clip() function which writes to the z-buffer but instead gives me horrible jagged edges on my textures which I absolutely do not want. I want to use blend.
So how do I do this? How do I achieve transparent objects that write to the z-buffer?
First, the post processing is using the camera depth texture. The camera depth texture is not the depth / z buffer. It’s a copy of a depth buffer either made from rendering all opaque queue objects’ shadowcaster pass to a full screen texture prior to rendering the real view, or a copy of the depth buffer after rendering out the gbuffers (which is also only opaque queue objects) if using deferred rendering.
What that means is you can have transparent objects that render to the depth buffer, but that will still have no impact on the post processing since the camera depth texture isn’t the depth buffer and nothing you render during the transparent queues will affect it.
If you move your objects to the opaque queue, and they have a shadowcaster pass, they’ll render to the camera depth texture. This will also break sorting for the transparent objects if there are more than one of them since opaque sorts front to back and transparency needs back to front, and break shadows (and potentially all lighting when using deferred) for all objects behind those transparent objects. This can work if the transparent object is very close to the opaque objects it’s covering, like adding paint stripes to a wall, but if that was your use case it wouldn’t be a problem either way.
The second option is you could inject your transparent objects into the camera depth texture using a command buffer by setting the camera depth texture as a render target and re-rendering your transparent objects manually using a shader that writes out the depth as its color value, and uses BlendOp Max. However this will still leave you with a jagged edge since you’ll need to use clip() when drawing to the depth.
The TLDR version: No, and you don’t want to. You need to use custom shaders on everything to do the color changing on the objects rather than using a post process, at least for transparent objects.