I am writing a Vulkan video manipulation engine which has the following layers:
- Foreground (2D)
- Scene (3D)
- Background (2D)
Note that each layer may have multiple objects, some of which may be transparent. For 2D objects (foreground and background), I want to preserve the relative between objects. Therefore, I thought about the following technique, in order to execute the FS the least amount of times possible:
- Draw the opaque foreground objects backwards, writing 0x02 at the stencil buffer.
- Draw the opaque scene objects backwards (sorted by average depth), writing and testing 0x01 at the stencil buffer and writing and testing at the depth buffer.
- Draw the opaque background objects backwards, writing and testing 0x00 at the stencil buffer.
- Draw the transparent background forwards, writing and testing 0x00 at the stencil buffer.
- Draw the transparent scene objects forwards (sorted by average depth), writing and testing 0x01 at the stencil buffer and writing and testing at the depth buffer.
- Draw the transparent foreground forwards, writing and testing 0x02 at the stencil buffer.
However, this technique does not work as specified, as the relative order between transparent and opaque objects at the background and foreground won't be preserved. This other technique would satisfy the condition (regardless of cherry picking OIT issues) although it is not efficient:
- Draw all the background objects forwards
- Draw the opaque scene objects backwards (sorted by average depth), writing and testing at the depth buffer.
- Draw the transparent scene objects forwards (sorted by average depth), writing and testing at the depth buffer.
- Draw all the foreground objects forwards
I would like to know if there is any technique with Vulkan that lets me implement the first algorithm without the mentioned problems. I've thought about a secondary depth buffer in which the relative order between 2D layers gets written (write and test a constant), but this leads me to a new concern:
According to some posts, if gl_FragDepth gets written from a shader (remember that I pretend to write a constant value from an uniform buffer to the depth value), fragment shader gets fully executed, which throws away the purpose of this optimization.