Selective UnrealBloomPass issues

Hi guys, I’ve been struggling (for days) to get the effect I want:

-Transparent background (no black)
-Just particles/balls being light-up/bloomed/glowing
-Container cuboids not to be light-up/bloomed/glowing
-Resolution to be something reasonable (As as soon as I applied it become pixellated?)

Find here the outcome at the moment:

(no bloom being shown, all meshes randomly light up but with no glow

If I set this to false: bloomComposer.renderToScreen = true

All the meshes light up but the black canvas background comes back (so no transparent background)

The code I am using at the moment related to that is the following:

  const bloomLayer = new THREE.Layers(),
  params = {
    exposure: 1,
    bloomStrength: 1,
    bloomThreshold: 0,
    bloomRadius: 0,
    scene: 'Scene with Glow',
  },
  ENTIRE_SCENE = 0,
  BLOOM_SCENE = 1,
  darkMaterial = new THREE.MeshBasicMaterial({ color: 'black' }),
  materials = {},
  renderScene = new RenderPass(scene, camera),
  bloomPass = new UnrealBloomPass(new THREE.Vector2(width, height), 1.5, 0.4, 0.85),
  bloomComposer = new EffectComposer(renderer),
  finalPass = new ShaderPass(
    new THREE.ShaderMaterial({
      uniforms: {
        baseTexture: { value: null },
        bloomTexture: { value: bloomComposer.renderTarget2.texture },
      },
      vertexShader: document.getElementById('vertexshader').textContent,
      fragmentShader: document.getElementById('fragmentshader').textContent,
      defines: {},
    }), 'baseTexture',
  ),
  finalComposer = new EffectComposer(renderer)

Then I set the following properties and so forth, as per https://threejs.org/examples/?q=bloom#webgl_postprocessing_unreal_bloom_selective the following:

finalComposer.renderTarget1.texture.format = THREE.RGBAFormat
finalComposer.renderTarget2.texture.format = THREE.RGBAFormat


bloomPass.threshold = params.bloomThreshold
bloomPass.strength = params.bloomStrength
bloomPass.radius = params.bloomRadius
bloomComposer.renderToScreen = true
bloomComposer.addPass(renderScene)
bloomComposer.addPass(bloomPass)
finalComposer.addPass(renderScene)
finalComposer.addPass(finalPass)
finalPass.needsSwap = true

bloomLayer.set(BLOOM_SCENE)

and then in the animation loop:

    const startAnimationLoop = () => {
      bloomComposer.render()
      finalComposer.render()
      window.requestAnimationFrame(startAnimationLoop)
    }

Would be amazing to know how to achieve the following effect https://threejs.org/examples/?q=bloom#webgl_postprocessing_unreal_bloom_selective just for the particles inside and still retain transparent background + a reasonable resolution (no antialiasing seems to apply with postprocessing?)

Can you please share a your code as a working live example (https://jsfiddle.net/f2Lommf5/)? Sharing a github repo is also a good idea. It’s more likely to get useful feedback by providing debugging options.

1 Like

Thanks for providing the ready to go fiddle.

Will surely do.

1 Like

Hi @Mugen87, been trying to replicate a minimum reproducible environment but it seems the js version of the UnrealBloomPass is creating some issues:

https://jsfiddle.net/fe87w5jb/14/

See console.log as follows:
UnrealBloomPass.js:141 Uncaught TypeError: Cannot read property ‘prototype’ of undefined

Bearing in mind I am using the following to link to the normal js version of UnrealBloomPass.js: //cdn.rawgit.com/mrdoob/three.js/master/examples/js/postprocessing/UnrealBloomPass.js

EDIT: apparently solved by the following fiddle that I am working on reproducing:
https://jsfiddle.net/c4192zfr/11/

@Mugen87 Apologies about the delay, the script thing leeched time from it:

https://jsfiddle.net/c4192zfr/20/

As you can see:

-Everything seems like deprived of antialiasing, which wont’ be a problem I guess as I am going to “bloom” just the particles inside the boxes (see first screenshot I attached) after I figure out how to do selective blooming…
-The bloom dissapears unless you set

bloomComposer.renderToScreen = false

or comment out:

// finalComposer.render()

This by the way makes the background of the canvas black again…

Any help would be greatly appreciated, thanks :pray:

After some debugging and research I’ve found out that UnrealBloomPass does not support transparent backgrounds right now, see:

You need this because of your CSS styled background, right? A workaround could be the usage of Scene.background. So create the background as an image, load it as a texture (via THREE.TextureLoader) and apply it to Scene.background. In this way, you don’t have to set alpha to true when creating the renderer.

First of all, thanks so much, knowing that after days of frustration is an instant serotonin hit :joy:

Exactly, I got a css styled background (precisely a gradient…to complicate things a bit)…

I will try to set it as a texture (a gradient .png texture 1366x768px should suffice) and remove the alpha propriety from the render.

To solve my last issue: as you can see the cube rotating is highly not antialiased, is it just because the bloom effect has been applied? or is it caused by something else? (a mistake in the render/passes etc.?) as I don’ see this “visual artifact” in other examples such as: https://jsfiddle.net/yp2t6op6/3/ or three.js webgl - postprocessing - unreal bloom

Thanks again for your help!

You have to setup the renderer first (setting its size), then the composers. Otherwise the internal render targets of EffectComposer will be too small.

BTW: It’s also a good idea to avoid fixed values for width and height. Try to use the following setting in order to render in the highest possible resolution.

https://jsfiddle.net/dq30h16w/

After expermeting I came to the following conclusions (please do prove me wrong otherwise there’s little I can do to achieve what’s needed).

Fiddle: https://jsfiddle.net/MelMacaluso/qrg9ekzo/2/

  1. Your suggestion of smartly setting the scene background as texture works but has issues: it seems the bloom properties such as, and mostly, exposure, influence also the background texture (please see following screenshot)
  2. If I set the exposure to a lower level to avoid that, the balls are not correctly bloomed anymore:
  3. Still, need to understand how to selectively do bloom post-processing ie. not blooming the cube but blooming the spheres (providing problems 1/2 are solved somehow unless is a limitation and just plain setClearColor() is supported
  4. If I set the background to black or a dark texture everything seems to be working fine in terms of blooming:

Tried to experiment with the actual code of the official threejs example but anything other than a black/very dark background has issues.

More than welcome to embrace alternatives or work arounds

1 Like

If you take a closer look at the original example, you can see that in simplified way it works like this:

const startAnimationLoop = () => { 

    scene.traverse( darkenNonBloomed );
    bloomComposer.render();
    scene.traverse( restoreMaterial );
    finalComposer.render();

    requestAnimationFrame(startAnimationLoop) 

}

Means you have to make non-bloomed objects totally black (and make the background black too), then render the scene with bloom composer, then restore all the materials (and restore the background too), then render the scene with final composer.

Take a look at these topics for reference: Instancing + selective bloom and Totentanz (Selective Bloom)
Pay attention to the replies from @looeee in the second topic.

3 Likes

I will try that out tomorrow, thanks a lot for your kind help :pray:

I seem to keep needing selective bloom recently and using multiple composers is pretty messy, so I updated the UnrealBloomPass to do it directly. I was planning to spend some time to see if there’s a more performant way of excluding the non-bloomed objects, but so far it seems to be OK. You can try it out if you like.

https://pastebin.com/jtk5d30f

Used exactly like the old bloom pass, it will bloom the whole scene:

const pass = new UnrealBloomPass( resolution, strength, radius, threshold );

But there’s some extra params you can pass in:

const pass = new UnrealBloomPass( resolution, strength, radius, threshold, selectedObjects, scene, camera );

Pass in your main scene and camera, and selectedObjects is an array of objects from your scene that you want to bloom.

You may also need to update UnrealBloomPass.changeVisibilityOfNonSelectedObjects() to get the effect you need, try switching between color write and visible:

 changeVisibilityOfNonSelectedObjects: function ( bVisible ) {
 
        var self = this;
 
        this.scene.traverse( function( child ) {
 
            if( child.isMesh && ! self.selectedObjects.includes( child )) {
 
                child.visible = bVisible;
                // child.material.colorWrite = bVisible;
 
            }
 
        } );
 
    },

@MelMacaluso note that this is based on the ES6 module version of the bloom pass, while you’re using the old UMD version in the fiddle you linked above. You’ll need to update your code to use modules for this work. See any of the examples for how to do that, for example: https://threejs.org/examples/#webgl_postprocessing_unreal_bloom_selective

6 Likes

Thanks a lot for your explanation, and yes I do agree creating a out of the box solution is ideal, will try it out too and see what’s the outcome :pray:

ps: in my real project I am using the modules instead (but in jsfiddle I couldn’t find a way to do that as it doesn’t allow files to be in the project as far as I know).

1 Like

Thanks!

@prisoner849 This partially solved all problems (minus the black background that needs to be there as far as I am aware because of a limitation when it comes to the unrealbloompass and alpha transparency of the renderer).

The updated outcome is the following:

Nearly getting there…as mentioned to @sciecode, would be amazing to know why some colors are simply not displaying? ie. red or green… if you look closely the desaturated purple particles are meant to be red same goes for the very pale turquoise ones…

Found out why some colors are not displaying thanks to @sciecode, basically the bloom pass sort of creates this effect so in order to compensate for that one would need to darken them in advance.

This has the obvious side effect of not achieving the exact HEX that is needed but :man_shrugging:

The lacking transparency instead, also thanks to @sciecode is caused by the alpha propety missing in the shader, updated is now:

    <script type="x-shader/x-fragment" id="fragmentshader">
			uniform sampler2D baseTexture;
			uniform sampler2D bloomTexture;
			varying vec2 vUv;
			vec4 getTexture( sampler2D texelToLinearTexture ) {
				return mapTexelToLinear( texture2D( texelToLinearTexture , vUv ) );
			}
			void main() {
        gl_FragColor = ( getTexture( baseTexture ) + vec4( 1.0 ) * getTexture( bloomTexture ) );
        gl_FragColor.a =  getTexture( baseTexture ).a; // THIS did it
			}
		</script>

Here’s the updated outcome:

giphy%20(5)

4 Likes

Hi @looeee, thanks heaps for the selective bloom shader. It is exactly what I’ve been looking for and I’ve integrated it into my scene.

Unfortunately, I can’t seem to get it to work.
I’m calling it like this:
const bloomPass = new UnrealBloomPass(new THREE.Vector2(window.innerWidth, window.innerHeight), 1.5, 0.4, 0, bloomedObjects, this.scene, this.camera);

and bloomedObjects in an array of Object3D.

It works with the BloomPass here: three.js examples
Hence, I know I’ve set up the scene and everything correctly. Now I’m wondering if I call the SelectiveBloomPass in an incorrect fashion?

I’d highly appreciate your feedback. Kind regards

Sorry posted the question and found the answer.
As you suggested in your post. Switching to

child.material.colorWrite = bVisible; does the trick

1 Like