enter image description here

The image above best demonstrates what I'm trying to achieve. It's a transparent shader for objects, but wherever the objects with this shader intersect they don't add together but simply merge with the same amount of transparency.

It seems like a simple thing, but I can't tell if it's even possible from my understanding of how the shader pipeline works. From what I understand of the process (and please correct me if I'm wrong), a fragment is created by each independent object. Once all the fragments for each object are created, the depth buffer chooses which fragment to write to that pixel in the framebuffer at a time, layering them on top of each other, so to speak. Once they've all been added to the framebuffer, the final result becomes the pixel.

If I could access the individual fragments to compare them against each other before they get written ('layered') into the frame buffer, it would be a simple case of tracking them and discarding any extra fragments in the same pixel space that are part of this shader / render queue. But I don't think this is possible with OpenGL?

Is there perhaps another way I can achieve the same effect?

  • 1
    \$\begingroup\$ Fragments are blended into the frame buffer immediately, rather than kept in a queue and blended after all objects have been rendered. So you can't directly compare against an earlier fragment - only the blended result of everything rendered thus far. (Unless you're using certain order independent transparency techniques) There are still ways to get effects similar to what you show though, using Min blending or taking advantage of depth & stencil buffers to block multiple objects from rendering over the same destination pixel. \$\endgroup\$ – DMGregory Apr 9 '14 at 20:06
  • \$\begingroup\$ Thanks for the clarification, this is what I needed to know. I am interested in your suggestion for using the depth & stencil buffers to block multiple objects — can you expand your explanation on how I could do that? I can't use the BlendOp because I am using some color. \$\endgroup\$ – Essential Apr 10 '14 at 18:54
  • 1
    \$\begingroup\$ You could adapt this idea here: gamedev.stackexchange.com/questions/72731/… If this is for the same fog of war effect as your earlier question though, I think the mesh approach I mocked-up there would be simpler and more flexible. \$\endgroup\$ – DMGregory Apr 10 '14 at 18:56
  • \$\begingroup\$ Ah, I had not seen your new edit over there! \$\endgroup\$ – Essential Apr 10 '14 at 19:12

One way of doing this is using min blending. With Unity this can be set up in ShaderLab using the BlendOp command.

If your objects are all monochrome as seen here, you may simply be able to use min blending directly on the objects as they're rendered and avoid having an alpha channel at all. (White is transparent when using min blending.) Min blending also works on colors, but it will take the minimum of each RGB channel individually, which could lead to some weird effects (e.g. min of magenta and yellow will be red).

  • \$\begingroup\$ I've investigated BlendOp and it doesn't quite work as my background has a slight blue tint to it and so the actual results are not perfect. Although I have to give you a vote up as it does technically work for my B&W example above! \$\endgroup\$ – Essential Apr 10 '14 at 18:52

I would go by giving a z-order to your objects, and

  1. Draw all non-transparent objects
  2. Draw the transparent object which are closer first.

Using this order, the z-depth test will prevent from merging.


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.