Selective Bloom (parts of a single geometry)

Hi community!


Example: JSFiddle

It’s all started with this topic and its reference picture: Three.js light and shadow

I had no idea about how to make that fog/nebula in the central part of the picture, but I had a thought about how to create those zones of variable intensity of light on these kind of steps, usign Selective Bloom technique. And here is my attempt.

There are two geometries in the scene. Merged spheres and merged capsules (see CapsuleGeom() function).
And the main uniform globalBloom, that I added to materials by patching them with .onBeforeCompile
That uniform indicates what state of the scene you will render: 0 - render all the scene as is, 1 - leave the parts, that have to be glowing, with their colors, and the other parts/objects must be black (including background).

  uniforms.globalBloom.value = 1; // we'll render the scene with colours for glowing
  renderer.setClearColor(0x000000); // background is  black
  bloomComposer.render(); // render for glowing
  uniforms.globalBloom.value = 0; // we'll render the scene as is
  renderer.setClearColor(0x220511); // any colour you like for the background :)
  finalComposer.render(); // render as is + additive render of the scene with glowing parts

The patch for materials of non-bloomed objects is very simple:

	onBeforeCompile: shader => {
    shader.uniforms.globalBloom = uniforms.globalBloom;
    shader.fragmentShader = `
      uniform float globalBloom;
      `#include <dithering_fragment>`,
      `#include <dithering_fragment>
        if (globalBloom > 0.5) {
        	gl_FragColor.rgb = vec3(0);

We add it to the very end of fragment shader here, so it’s guaranteed that we’ll get the pure black color when we render the scene for bloom.

For bloomed objects we could leave materials as is, but in this case we would get them just evenly glowing, which is not our goal.
So, we do this:

    onBeforeCompile: shader => {
  	shader.uniforms.globalBloom = uniforms.globalBloom;
    shader.uniforms.time = uniforms.time;
    shader.vertexShader = `
    	varying vec3 vPos;
    	`#include <fog_vertex>`,
      `#include <fog_vertex>
      	vPos = position; // pass position in local coords
  	shader.fragmentShader = `
    	uniform float globalBloom;
      uniform float time;
      varying vec3 vPos;
    	`#include <color_fragment>`,
      `#include <color_fragment>
      	vec2 lUv = vPos.xz /  10.; // compute uv from the local position
        lUv *= 3.;
      	float fade = clamp(simplex_noise(vec3(lUv, time)) * 0.5 + 0.5, 0., 1.);
        fade = pow(smoothstep(0., 0.875, fade), 12.); // "shaping" the intensity [0..1]
      	if (globalBloom > 0.5){
         	diffuseColor.rgb *= fade * 0.95 + 0.05; // for bloomComposer
        } else {
        	diffuseColor.rgb += fade; // for finalComposer

The main idea is to have different parts of a geometry with different intensity of color, when we render the scene for glowing. In the above block of code, the value of fade is the thing that controls the intensity (in my case it’s based on the simplex noise, but it may be based on a texture or something else).

PS Criticism and advice are welcomed :slight_smile:
PPS The original function for capsules is here


Amazing :love_you_gesture: :laughing:

1 Like

Great work as always :star_struck:

1 Like

@Light @looeee thanks, guys :beers:

Wonderful demo !

I tried to make a variant with UV :

:man_dancing: disco time :dancer:

edit prisoner


@felixmariotto COOL :star_struck:

Oh, that’s amazing thank you , but i have a question , how can i make the bloom effective only at lines , cuz if i add any object to the scene look very bloomy ?

@lolia But in the demo, only the lines are affected by bloom; spheres are not glowing. :thinking:

Yes , but you add shader code in it’s material is that necessary to stop sphere glowing ?

Perfectly correct.

1 Like

This example cannot be accessed. It may be cross domain. Any other addresses.

Which example? :thinking: Both mine and from @felixmariotto are working.