Unreal Bloom Pass Effect on Shader Materials?

I am trying to create a background for my scene where it consists of moving clouds, sun, and a sky. I finally was able to get the sun beaming using an unreal bloom pass effect, but I believe that effect is the reason my scene looks very gray and cloudy now.

I’ve combed through so many docs, blogs, Q&A posts, and CodePens to try to fix this problem so I’m pretty stuck on what else to try. I read in other posts that you can have just one object in a scene glow using this effect, but the problem is the clouds and sky use a shader material instead of the standard mesh material so that’s why I think I can’t set emissiveIntensity on it to determine which object should glow in the scene.

I only want the effect on the Sun component:

const Sun = () => {
  const sunColor = new Color(0xffdd16);

  return (
    <>
      <Effects disableGamma>
        <unrealBloomPass threshold={1} strength={0.5} radius={1} />
        <outputPass args={[ACESFilmicToneMapping]} />
      </Effects>
      <mesh position={[1, 40, 5000]}>
        <sphereGeometry args={[95, 50, 50]} />
        <meshStandardMaterial
          color={sunColor}
          toneMapped={false}
          emissive={sunColor}
          emissiveIntensity={3}
        />
      </mesh>
    </>
  );
};

But it affects the whole scene (sorry, the Clouds component is pretty long but I used a shader material in a similar way as the Sky component):

return (
    <shaderMaterial
      name='Sky'
      uniforms={uniforms}
      vertexShader={vertexShader}
      fragmentShader={fragmentShader}
      side={BackSide}
      attach='material'
      emissiveIntensity={0}
    />
  );

Adding the emissiveIntensity doesn’t seem to fix the problem unfortunately, does anyone know what I can do to get the scene back to its original vibrance? I’ve also tried using layers, but that would just hide certain components.

Goal/Original:

Current (after adding in Effects):

1 Like

check if your shadermaterial has these two includes

 #include <tonemapping_fragment>
 #include <colorspace_fragment>

getting this srgb/tonemapping stuff right has become very hard, i can never remember the specific steps that three requires. but maybe share your box as a codesandbox, i might be able to have a look.

ps i like the desaturated look actually, but that’s beside the point :smiley:

pps, better use shaders like this ThreeJS Journey Portal - CodeSandbox it makes them reusable and easier to digest. you also don’t need “attach=‘material’”

1 Like

emissiveIntensity is just a specific way of adding to the brightness of a surface. What matters is the total brightness of the surface relative to the bloom pass’s threshold.

Without a demo it’s hard to say exactly what might be going on here (can you share a codepen or similar?) but you might try…

  • disable bloom, just keep output pass
  • disable output pass, just keep bloom

… to isolate where the difference is coming from. Or raise the threshold significantly (say, 1000) so that nothing blooms, then work from there.

1 Like

@drcmda @donmccurdy Thank you so much for your answers! I do have a sandbox to share since I feel like I’m not giving as much context (I stripped it down to just the background-related parts of the scene).

I’m happy with any reasonable solution that makes the scene less muted whether that involves tweaking the shaders, the effects, both, or some other thing. :smiley:

ps i like the desaturated look actually, but that’s beside the point :smiley:

I feel you. If I wasn’t already going for a perky, upbeat tone, then I would have just given up and left it as is. :joy:

No one has a clue on how I can proceed?

With no lit shading happening in this scene, you may want to simplify things and remove the tone mapping, it is meant for lit scenes. Adding <Canvas flat={true} ... is enough.

THREE.OutputPass does not take arguments, so note that this line is doing nothing:

<outputPass args={[ACESFilmicToneMapping]} />

If the sky were meant as the background to a lit scene, and you did need tone mapping for this scene, I believe you would want a brightness multiplier for the sky, clouds, and sun, such that these scalars can be adjusted carefully:

  • renderer.toneMappingExposure
  • sun/sky/cloud multiplier
  • scene lighting
  • bloom threshold

But for the example as shown, that is unnecessary.

1 Like

The bloom is not supposed to affect the background or the environment

That appears to be a smaller factor in the “goal vs. current” screenshots above, so I’m advising to solve one thing at a time and deal with the tone mapping difference first. But the bloom would be further constrained by raising the bloom threshold, along with the brightness of the sun.

1 Like

Thank you, this definitely helped me get towards the right direction. <Canvas flat={true} gl={{ toneMappingExposure: 0.1, }} got rid of a lot of the overcast effect on the scene.

What do you mean by multiplier? Not the emissiveIntensity, right? Because that seems like hopefully the last step to get the scene close enough to my goal. I just need the clouds to have more of a contrast.

emissiveIntensity is a property of some materials that three.js provides, such as THREE.MeshStandardMaterial, and its effect is equivalent to:

gl_FragColor.rgb += emissiveColor.rgb * emissiveIntensity;

In a custom ShaderMaterial there is no emissiveIntensity property, as you are providing the shading model yourself, but you can include similar code in your GLSL.

1 Like