I have a brainteaser that seemed trivial initially and has somewhat spiralled out of control for my brain – I could really use your help and any hint or idea is MUCH appreciated. I’ve been doing a lot of experiments and also research here on the forum and elsewhere but couldn’t find a good solution.
Let me describe the problem as short as possible: I have a varying amount of meshes in my scene. The idea is that I want them to visually blend, when overlapping, in a way that is similar to Photoshop’s “difference” mode.
A bit more detail: When you add one mesh with a white color on top of a white background, a “difference” blend operation would result in the mesh appearing as the inverse, so black. If you add a second mesh and have it overlap/intersect the other mesh, a “difference” would lead to the overlapping parts being white. If you add a third mesh and have all three overlap, you can see that the part where all three overlap becomes black again. And so forth… Here is an image:
So, one can see that the order of the elements is important to arrive at the correct color.
Use Three.js’s integrated custom blend equations: While it gives you a lot of opportunities, I feel this wasn’t a helpful route as they essentially always use a singular source and destination. I’m not sure it’s possible to replicate the “difference” blend mode with just one source and destination as the order of elements feels important. I couldn’t find a solution where this approach makes sense.
Use render-targets and the PostProcessing composer: That seemed like a smart move, I can simply write my own shader to replicate the equation. The actual operation should be as simple as “vec3 diff = abs(background.rgb - overlay.rgb);”. Right? Well, it seems not really as I run into the same problem: There is no order – all meshes are part of the overlay renderTarget, so the operation inverts the total shapes, not singular ones in the correct order.
Use a custom ShaderMaterial per mesh: It feels, like this needs to happen per mesh. But the problem is: What texture-reference do I use within the mesh-shader? Would that mean that I need to create one texture-render/renderTarget per object and gradually render each mesh on top of the next one? I am not sure if there is a solution for some kind of ping-pong approach… But would that mean that for, lets say, 20 meshes I would need to do 20 consecutive renders per frame? That seems very inelegant and like a performance nightmare.
you could maybe have a render target with these meshes all having additive material with the color of 1 and then a custom shader on that target that would render white or black based on input color % 2
Hey! Thanks for your idea.
Could you explain a bit more what you mean? I set up a demo codepen if it helps to demonstrate your idea in code? https://codepen.io/patrikHuebner/pen/MWRewRv
Hey!
That sounds really interesting. Could you elaborate a bit more – especially on the third point? Either wide pseudocode, some references or editing the codepen?
I’ve set up a test codepen here: https://codepen.io/patrikHuebner/pen/MWRewRv
I’m not sure how to test the pixels where the stencil buffer is 0. Without that final step, my result – following your steps – currently looks like this:
That’s amazing. Thank you so much for your help! I need to read up on how this exactly works technically but it definitely creates the effect I was looking for.
kek, I thought I liked stencil idea better and spent like 10 minutes fixing your code and enabling orbit controls only to find out I did not scroll the page down oh well. to make the reply interesting, here are some funny angles:
May I trouble you once more? I’ve been trying to combine this stencil approach with text and was hoping that there is a chance to use a canvas as a texture on a plane and blend that with geometry. The desired outcome would be that the text becomes white where there is a black background and vice versa. Do you know if that is even possible? And if not: If there is any other approach? SDF-text, shaders?
I’ve set up a quick codepen where I’ve added a simple texture. I tried multiple stencil passes and operations but the texture doesn’t blend with the rest. Here is the codePen: https://codepen.io/patrikHuebner/pen/wvZXXrq
Hey!
I thought I had thanked you for your work – sorry for not actually doing that !!
Maybe I can trouble you once more? I just replied at the bottom of this thread with the question if there is a chance to the stencil operations on textures as well. So that I can blend text with geometry. If you have any ideas, I’d be thrilled !
Amazing, it does work. I’ve updated the codePen for others to follow along.
I really appreciate the help !! Thank you so much and have a great weekend.