Make NoBlending blending affect only the desired layer

I’m trying to render a scene by doing it in 2 calls, one that renders certain layer, and then another one that renders another layer.

I’m defining layers on objects via:

camera.layers.disable(1);
camera.layers.enable(0);
renderer.render(scene,camera);
camera.layers.disable(0);
camera.layers.enable(1);
renderer.render(scene,camera);

This is working great, I’ve managed to render one layer first, then the other one, and have them put one on top of the other.

But…

I’m trying to do some occlusion with Layer 1, it has materials with blending = THREE.NoBlending

Problem is, this NoBlending effect is also affecting the second-render layer. Thought it was going to render transparent, but it seems that the NoBlending is affecting both layers.

Is there a way I could have NoBlending occlusion effect to affect only certain objects or certain layers?

I tried rendering to another RenderTarget, and then use it as a texture, but that brings a lot of complexity that I want to avoid.

Any suggstions? :slight_smile:

Thanks in advance.

can you toggle the mesh.material.blending = xxxx for each mesh?

If you have a material with a blending as NoBlending, whatever is behind that material it won’t be rendered.

I’m trying to render the scene in 2 stages, because I do wanna have a plane drawn even tho it’s behind the NoBlending material. TL;DR; I wanna have certain objects/material still be drawn behind a NoBlending material blend.

I think i’m not understanding what you mean, because you can have a noblend material and a blending material in the same scene no problem.

Also I notice you’re not setting the layer on camera? So I’d expect in the second pass, that object isn’t getting rendered?

Maybe some pictures or higher level information about what you’re trying to make would be helpful.

Sorry, I was refactoring my code and didn’t have a visual.

I’m working on camera filters, and this is my setup:

  • I have a plane with my camera feed as a texture
  • A GLB is placed in front of the plane, that acts as the filter
  • The red that you see is the background of my <div/> that holds the renderer. (There is a material with NoBlending that lets you see thru, more than what I want tho)

I’m using the NoBlending material with the shape of a head, to occlude the rings behind my head, but it is also occluding the plan that is behind, and I don’t want to occlude the plane, just the rings.

I thought that if I rendered first the layer that has the plane, and then render the layer that has the filter it would work, but it is still occluding the plane, even tho each layer is rendered on its own.

Layer 0 = Camera Feed Plane
Layer 1 = GLB with occlusion

It seems that when I render the 2nd layer on top of the 1st one, it just deletes the pixels where there is NoBlending, instead of just placing “transparent” pixels.

As for your comment:

Also I notice you’re not setting the layer on camera?

I meant to write “camera” not “object”.

camera.layers.disable(1);
camera.layers.enable(0);
renderer.render(scene,camera);
camera.layers.disable(0);
camera.layers.enable(1);
renderer.render(scene,camera);

I think I understand now.
You want the red replaced by the video feed… and you also want the video feed as the background of the whole thing as well? So it will be rings orbiting around the users head, as long as they keep their head in the red area?

You may not need multiple passes to achieve this?
red object material = MeshBasicMaterial({
opacity:.0001
});

I want the red to occlude the back part of the rings, but not the plane that has my camera feed.

My material does not even have a red color, the red that you see is the background of my <div/> element that holds the canvas, canvas is transparent.

This is the material of the occluder:

material.color.set('black');
material.opacity = 0;
material.transparent = true;
material.blending = THREE.NoBlending;

You can see, how the set color is black. (but is not visible since it has the NoBlending blending)

The problem is that the NoBlending space is overriding with transparent pixels

If I were to only render the first layer

camera.layers.disable(1);
camera.layers.enable(0);
renderer.render(scene,camera);

I get this output:

So I can tell, I am able to successfully have the layers separated, and render the camera feed on its own.

But then, I render the second part, where it is only the rings + occluder material

camera.layers.disable(0);
camera.layers.enable(1);
renderer.render(scene,camera);

And I get this:

The second render is being placed on top of the first one, in an additive way except for the part where the occluder is, just on the NoBlending material, it seems to behave as replacing instead of additive, putting 100% transparent pixels there, instead of letting the first render see thru it.

Yeah I’m saying you don’t need multipass rendering for this. I’ve also had problems with opacity=0 in the past. I have seen it act as an “early out” where the renderer just skips the rendering. I’m also not seeing anywhere where you are disabling autoClear on the renderer… so I’m surprised that your multipass rendering is even working at all…
Usually if you call renderer.render twice… the second render clears all the display/depth buffer automatically, before rendering the pass.

You can disable/toggle it by:

render first pass
renderer.autoClear = false;
render second pass
renderer.autoClear = true; // restore the autoClear for the next frame.

But you should be able to achieve this effect with a single pass, and it will be more performant.

I do have renderer.autoClear = false; when I create the renderer, and then I call renderer.clear(); before rendering the first pass.

In my case, I see no difference if I set the alpha to be 0.0001 or 0

I got it working a little better by setting depthWrite of the occluder material to false

material.color.set('black');
material.opacity = 0.000001;
material.transparent = true;
material.depthWrite = false;
material.blending = THREE.NoBlending;

Screenshot 2024-03-23 at 1.50.20 p.m.

But still not want I want :frowning:, I want the occluder to not “affect” the plane that has my camera feed.

can you put this in a jsfiddle or a glitch and we can poke at it?

1 Like