Post Processing Effect on Select Nodes (Depth Sorting Issue)

Hi all. I have a simple two-pass blur filter and am trying to apply it to selected nodes. I’ve been trying quite a few different and radical approaches, but the closest I’ve gotten has an issue.

I have a few buffers: one full screen quad (made with renderSceneInto), one for the horizontal blur pass, another for vertical, and then one special one that I made that has a camera bitmask. This camera bitmask is what I’m using to render only objects that I want blurred.

I am isolating the node by:

render.hide(blur_bitmask)
node.hide(0) # The main cam bitmask
node.showThrough(blur_bitmask)

The problem with that is–there’s no render ordering on my special blur_bitmask buffer! If I’m only rendering objects I want, there’s nothing to occlude it from when a piece of geometry gets in front of it! I’ve seen things such as shareDepthBuffer, but I frankly have had no luck figuring out what it’s really doing. While I understand I can do a luminance test in this example, I was just using this bright cone as an example.

Hmm… Could you, instead of excluding non-blurred objects from your blur-buffer, rather have them render as black?

That way they should be present to occlude objects behind them–but shouldn’t contribute to the blurring. Or so it seems to me!

(forgot to press reply to you button)

This seems fine in theory, but how would I go about setting it to black only in the blur buffer and not in the primary one as well?

There may be better ways, but off the top of my head–and presuming that you’re using custom shaders for this–you could perhaps set a shader-input that’s used only by the shader on the blur-buffer.

(Maybe on a common root-node, if you find that you end up with too many shader-related states.)

So, something like this:

In Python:

self.nonBlurredNodePath.setShaderInput("doBlurring", 0)
self.blurryNodePath.setShaderInput("doBlurring", 1)

And then in GLSL:

uniform float doBlurring;

// Later...

color = color * doBlurring;

Something like that.

If you’re not using custom shaders, then I’m not sure offhand of how it might be done–it’s not something that I’ve looked into, myself. Perhaps someone else here will know–or maybe some digging through the forum will turn up something!

The only thing that has custom shaders are the quads that I’m using for the blur buffers. It’s not actually being applied to any real nodepaths. The horizontal quad has the horizontal blur pass (using the “blur-objects-only” buffer texture), vertical has the vertical blur pass (using the horizontal texture), and then I just combine the vertical with primary.

I can post a lightweight example shortly if it’ll help.

I dug up this old thread, which describes rendering colours for the purpose of picking–something similar in fundaments to what we’re discussing, I feel.

Specifically, I note that they indicate there that the colour-handling can be controlled by per-camera state-changes. They don’t specify, but perhaps something like a camera-level state that alters blend-modes and colours, or something like that?

1 Like

Specifically, I note that they indicate there that the colour-handling can be controlled by per-camera state-changes. They don’t specify, but perhaps something like a camera-level state that alters blend-modes and colours, or something like that?

Thanks–that did certainly help quite a bit. This can be done by set_tag_state in Camera. What I was going to do was add a ColorScaleAttrib to render for (0, 0, 0, 1) (like you suggested earlier) and then another to the node–though I assume if the node is a child of render, then the render’s ColorScaleAttrib will block the child’s.

…that didn’t actually work because you can only set one render attrib per tag state…so I tried to go around that by setting an initial state of my buffer’s cam to be black… and it worked!

blur_node.setTag("test", "True")

...
# Everything to be black by default on the blur buffer only.
self.output_cam.node().setInitialState(ColorAttrib.make_flat((0, 0, 0, 1)))

# Then everything with the "test" tag gets its regular color back.
self.output_cam.node().set_tag_state_key("test")
self.output_cam.node().set_tag_state("True",  ColorAttrib.make_vertex())

Thanks for the help!

1 Like

Ah, I’m glad that it my post did help! And well done on getting the feature to work! :slight_smile:

Hmm… If it were “setColor” rather than “setColorScale”, then the opposite is true, I believe: the setting on the child-node should override the setting on the parent-node (absent a priority being set on one or both).

That is, if the parent has “setColor(0.5, 0.5, 0.5, 1)”–i.e. a grey colour–applied, and the child has “setColor(0.5, 1, 1, 1)”–i.e. cyan–applied, then the parent will be grey, and the child will be cyan.

However, I believe that “setColorScale” composes, instead–that is, that the colour-scale of a given node is equal to the colour-scale on that node multiplied by the colour-scales of every node above it.

So, if again the parent has “setColorScale(0.5, 0.5, 0.5, 1)” applied and the child has “setColorScale(0.5, 1, 1, 1)” applied, then the parent will again be grey–but the child will be dark cyan–i.e. the cyan applied to the child multiplied by the grey applied to the parent, for a total scale of (0.25, 0.5, 0.5, 1), if I’m not much mistaken.